# CI/CD Failure Explorer > Paste CI logs from several runs: root cause per run, grouped signatures, top causes and fixes. Paste or upload logs of several GitHub Actions, GitLab CI or Jenkins runs (separated by "=== run: name ===" lines). Each run is classified by a documented pattern catalogue — test assertions (with test names), compile/type errors, dependency resolution, network/registry timeouts, OOM/exit 137, disk full, timeouts, lint, flaky retries, missing secrets/permissions — and runs are grouped by normalised error signature with counts per branch and day. Part of usefulweb.site (https://usefulweb.site/). Results are deterministic calculations from the inputs and the listed assumptions; the API returns exactly what the web page shows. ## Use it - Human interface: https://cicdfailureexplorer.usefulweb.site/ (interactive tool at https://cicdfailureexplorer.usefulweb.site/tool) - JSON API: POST https://cicdfailureexplorer.usefulweb.site/api/v1/calculate with a JSON object of inputs (schema: https://cicdfailureexplorer.usefulweb.site/api/v1/tool) - OpenAPI: https://cicdfailureexplorer.usefulweb.site/openapi.json - MCP (Streamable HTTP): https://cicdfailureexplorer.usefulweb.site/mcp - tool `cicd_failure_explorer` ## Inputs - logs (textarea): CI logs - Separate runs with a line "=== run: ===". Optional metadata in the header: branch=…, date=YYYY-MM-DD, status=failed|passed. Without separators the whole paste is one run. - file (file): Or upload a log file - Plain-text log export (UTF-8). Combined with any pasted text. ## Method - Runs are split at lines "=== run: ===" (header metadata branch=, date=, status= is honoured). ANSI colours, GitHub timestamp prefixes and GitLab section markers are stripped. - Platform is detected from runner markers (##[group]/##[error], "Running with gitlab-runner", "[Pipeline]"/"Finished: …"). Status comes from the header, then from terminal markers (Process completed with exit code, ERROR: Job failed, Finished: FAILURE/SUCCESS). - Every line is matched against a catalogue of documented error markers per cause. When several causes appear, the one with the highest causal priority wins: OOM/exit 137 → disk full → timeout → permission/secret → network → dependency → compile → lint → test → flaky → cancelled (e.g. a test crash after an OOM kill is reported as OOM). - The first matching line is the evidence; its normalised form (paths, SHAs, UUIDs, timestamps, IPs, line numbers and durations replaced by placeholders) is the signature used to group runs. Test failures are grouped by the sorted names of the failing tests. - Failing test names are extracted from jest/vitest (●/×), pytest (FAILED a::b), go test (--- FAIL), Maven Surefire ([ERROR] Class.method), Gradle (> … FAILED), TAP/node:test (not ok) and RSpec (rspec ./spec …). - Flaky suspects: tests that fail in some runs of a job but other runs of the same job (name without #number) pass, and passing runs that contain retry markers. - Unclassified failures are labelled with the closest match from the Error Message Translator pattern database when possible.