SBOMFlow Exit Codes
SBOMFlow uses stable exit codes for CI and operator scripts.
| Code | Meaning | Typical cause |
|---|---|---|
| 0 | Success | Command completed, or a release gate was informational/not enforced. |
| 1 | Enforced release gate failed | A manufacturer-selected --fail-on-* policy blocked the run. |
| 2 | Usage, input, IO, or config error | Missing target directory, malformed config, bad arguments, or unwritable output. |
| 3 | Init refused / bundle verification failed | sbomflow init found an existing sbomflow.yaml without --force, or sbomflow verify-bundle found a tampered bundle / failed signature. |
| 4 | Structural validation failure | sbomflow validate or sbomflow audit found malformed/tampered artifacts. |
| 5 | Strict warnings-as-errors | analyze --strict (or --strict=code1,code2) matched one or more scan warnings after artifacts were written. |
No subcommand is treated as usage error: sbomflow prints help to stderr and exits 2. Gate failures are distinct from structural validation failures so CI can separate manufacturer policy decisions from broken artifact integrity.
Troubleshooting first-run failures
Common mistakes are designed to self-explain with an actionable message:
- Missing/file target (
exit 2) — "target directory not found … Fix: pass an existing product directory." - Malformed or unknown-key config (
exit 2) — the parser error plus "Fix: check syntax/keys withsbomflow validate-config <file>or runsbomflow doctor .." - Unknown
--policy-profile(exit 2) — lists the available shipped presets. - Malformed
--kev-file/--epss-file/--nvd-filesnapshot — never silently ignored: it surfaces avulnerability_enrichment_errorscan warning (and fails under--strict).
sbomflow doctor . is the first stop: it reports Python compatibility, optional extras, the external CycloneDX CLI, and any discoverable config (including parse errors and unknown-key warnings) — all offline.
--strict is opt-in and runs after all artifacts are written, so the evidence pack is always produced; the distinct exit code 5 lets CI fail on warnings without conflating them with a --fail-on-* gate decision (1). Each scan-warning code is registered in the stable catalog (src/sbomflow/warning_catalog.py, version sbomflow-warning-catalog-v1); --strict=<codes> is validated against it.