Exit codes
| Code | Meaning |
|---|---|
0 |
Scan completed; nothing reached the failure threshold. |
1 |
Findings reached the --fail-on threshold, or a file could not be analyzed. |
2 |
Invalid configuration or CLI option. Nothing was analyzed. |
3 |
Internal error, including a path that does not exist. |
--fail-on=never reports findings but always exits 0.
test (since 1.2.0)
Section titled “test (since 1.2.0)”Runtime replay uses the same four codes, reading “expectation” for “finding”:
| Code | Meaning |
|---|---|
0 |
Every expectation held. |
1 |
At least one expectation did not hold. |
2 |
The scenario or an option was invalid. |
3 |
A request could not be completed — connection refused, timeout, incomplete or malformed response. |
3 is deliberately not 1. A request that never completed observed nothing
either way, so it is not evidence about state: a response whose body stops short
of its Content-Length cannot satisfy body_not_contains, because the rest of
it never arrived. On a transport error nothing is written to stdout, including
in --format=json.
A file that could not be parsed or read at all is not a finding — it is a gap in
the evidence, so it fails the scan on its own. The console output says which
files and why. Pass --allow-parse-errors (or set fail_on_parse_error: false)
to downgrade that to a warning.
Be precise about what this means: a scan is complete when no file was skipped
entirely, not when every file parsed without a single error. A syntax error
php-parser recovers from leaves the scan complete, because the file was still
analyzed — it is reported as a parse warning instead. Both counts are in the
JSON report (summary.parse_errors and summary.files_not_analyzed), and
summary.incomplete is the one that gates the build.