Exit Codes¶
abicheck uses different exit codes for each command family.
Why they differ: compare is the native interface with a wider exit code range (0/1/2/4) that distinguishes tool errors from API breaks from binary breaks. compat mirrors abi-compliance-checker exit codes (0/1/2) so existing ABICC CI scripts work without changes.
abicheck compare¶
Legacy exit codes (default, no --severity-* flags)¶
| Exit code | Meaning |
|---|---|
0 |
NO_CHANGE, COMPATIBLE, or COMPATIBLE_WITH_RISK — no binary ABI break |
2 |
API_BREAK — source-level API break — recompilation required |
4 |
BREAKING — binary ABI break |
⚠️ Exit
0coversNO_CHANGE,COMPATIBLE, andCOMPATIBLE_WITH_RISK. If your pipeline needs to distinguish them (e.g. warn on deployment risk), use--format jsonand read theverdictfield — exit code alone is not sufficient.
Severity-aware exit codes (with any --severity-* flag)¶
When any --severity-preset or --severity-* option is provided, the exit code
is computed from the severity configuration rather than the verdict:
| Exit code | Meaning |
|---|---|
0 |
No error-level findings |
1 |
Error-level findings in addition or quality_issues only |
2 |
Error-level findings in potential_breaking (but not abi_breaking) |
4 |
Error-level findings in abi_breaking |
The highest applicable code wins. For example, if both abi_breaking=error and
quality_issues=error have findings, the exit code is 4.
ℹ️ The two exit code paths are mutually exclusive. Without
--severity-*flags, the legacy verdict-based path runs. With any--severity-*flag, the severity-aware path runs. They never both execute.
Severity presets¶
| Preset | abi_breaking |
potential_breaking |
quality_issues |
addition |
|---|---|---|---|---|
default |
error | warning | warning | info |
strict |
error | error | error | error |
info-only |
info | info | info | info |
Per-category overrides (--severity-abi-breaking, --severity-potential-breaking,
--severity-quality-issues, --severity-addition) take precedence over the preset.
CI gate patterns¶
# Production gate: fail on any break (legacy exit codes)
abicheck compare old.json new.json
ret=$?
[ $ret -eq 4 ] && echo "BREAKING — release blocked" && exit 1
[ $ret -eq 2 ] && echo "API_BREAK — source-level break" && exit 1
echo "OK (NO_CHANGE or COMPATIBLE)"
# Block unexpected API expansion (severity-aware)
abicheck compare old.json new.json --severity-addition error
ret=$?
[ $ret -eq 1 ] && echo "ADDITIONS — unexpected API expansion" && exit 1
[ $ret -eq 4 ] && echo "BREAKING — release blocked" && exit 1
[ $ret -eq 2 ] && echo "API_BREAK — source-level break" && exit 1
echo "OK"
# Strict mode: all categories at error level
abicheck compare old.json new.json --severity-preset strict
# Permissive gate: fail only on binary breaks
abicheck compare old.json new.json
ret=$?
[ $ret -eq 4 ] && exit 1 # BREAKING only; API_BREAK (exit 2) allowed
exit 0
# Parse exact verdict from JSON (with severity info)
abicheck compare old.json new.json --format json --severity-preset default -o result.json
verdict=$(python3 -c "import json,sys; d=json.load(open('result.json')); print(d['verdict'])" \
|| { echo "ERROR parsing result.json"; exit 1; })
[ "$verdict" = "BREAKING" ] && exit 1
abicheck appcompat¶
Uses the same exit codes as compare:
| Exit code | Meaning |
|---|---|
0 |
COMPATIBLE or NO_CHANGE — application is safe with the new library |
1 |
Tool/runtime error (tool failure, invalid input, or unexpected exception) |
2 |
API_BREAK — source-level break affecting app's symbols |
4 |
BREAKING — binary ABI break or missing symbols |
BREAKING(exit 4) is also returned when the application requires symbols or ELF version tags that are absent from the new library — even if the library diff itself is compatible — because the application would fail to load.
abicheck deps¶
| Exit code | Meaning |
|---|---|
0 |
All dependencies resolved, all required symbols bound |
1 |
Missing dependencies or unresolved symbols (binary would fail to load) |
abicheck stack-check¶
| Exit code | Verdict | Meaning |
|---|---|---|
0 |
PASS |
Binary loads and no harmful ABI changes |
1 |
WARN |
Binary loads but ABI risk detected in dependencies |
4 |
FAIL |
Load failure or binary ABI break in dependencies |
CI gate patterns¶
# Full-stack check: fail on FAIL, warn on WARN
abicheck stack-check usr/bin/myapp --baseline /old-root --candidate /new-root
ret=$?
[ $ret -eq 4 ] && echo "FAIL — load failure or ABI break" && exit 1
[ $ret -eq 1 ] && echo "WARN — ABI risk detected" && exit 1
echo "PASS"
# Permissive: only fail on load failure / ABI break
abicheck stack-check usr/bin/myapp --baseline /old-root --candidate /new-root
ret=$?
[ $ret -eq 4 ] && exit 1 # FAIL only; WARN (exit 1) treated as OK
exit 0
abicheck debian-symbols¶
debian-symbols generate¶
| Exit code | Meaning |
|---|---|
0 |
Symbols file generated successfully |
1 |
Error (binary not found, ELF parse error, I/O failure) |
debian-symbols validate¶
| Exit code | Meaning |
|---|---|
0 |
Symbols file matches the binary (all required symbols present) |
2 |
Mismatch — one or more required symbols are missing from the binary |
Symbols tagged
(optional)are not required — their absence does not cause exit code2. This matchesdpkg-gensymbolsbehaviour.
New symbols found in the binary but not listed in the symbols file are reported in the output but do not change the exit code.
debian-symbols diff¶
| Exit code | Meaning |
|---|---|
0 |
Diff computed successfully (regardless of whether changes were found) |
1 |
Error (file not found, parse error) |
CI gate patterns¶
# Update symbols file when library changes
abicheck debian-symbols generate ./build/libfoo.so \
--package libfoo1 --version "$(dpkg-parsechangelog -SVersion)" \
-o debian/libfoo1.symbols
# Validate symbols file in CI (fail on missing symbols)
abicheck debian-symbols validate ./build/libfoo.so debian/libfoo1.symbols
ret=$?
[ $ret -eq 2 ] && echo "FAIL — symbols file needs updating" && exit 1
echo "OK — symbols file matches binary"
# Diff before/after to see what changed
abicheck debian-symbols diff old.symbols new.symbols
abicheck compat¶
Matches abi-compliance-checker exit codes (ABICC drop-in):
| Exit code | Meaning |
|---|---|
0 |
No breaking changes (NO_CHANGE or COMPATIBLE) |
1 |
BREAKING (mirrors ABICC) |
2 |
API_BREAK (source-level break; non-verdict failures use extended codes below) |
Non-verdict/tool failures are classified via Extended compat error codes (ABICC-style) below (
3,4,5,6,7,8,10,11).
Extended compat error codes (ABICC-style)¶
In abicheck compat, non-verdict failures are further classified where possible:
| Exit code | Typical cause |
|---|---|
3 |
Required external command/tool is missing (for example castxml) |
4 |
Cannot access input files (missing or permission denied) |
5 |
Header compile/parsing failure during dump |
6 |
Invalid compat configuration/input (descriptor, suppression, regex flags) |
7 |
Failed to write report/output artifact |
8 |
Dump/analysis pipeline failure |
10 |
Generic internal/tool failure fallback |
11 |
Interrupted run |
Note: classification is best-effort and context-dependent;
API_BREAKremains2.
Summary table¶
| Verdict / State | compare exit (legacy) |
compare exit (severity) |
appcompat exit |
deps exit |
stack-check exit |
debian-symbols validate exit |
compat exit |
|---|---|---|---|---|---|---|---|
NO_CHANGE / PASS |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
COMPATIBLE |
0 |
0 |
0 |
— | — | — | 0 |
COMPATIBLE_WITH_RISK |
0 |
0–2* |
0 |
— | — | — | 0 |
| Additions only | 0 |
0–1* |
n/a | — | — | — | n/a |
| Quality issues only | 0 |
0–1* |
n/a | — | — | — | n/a |
WARN (ABI risk) |
— | — | — | — | 1 |
— | — |
API_BREAK |
2 |
0–2* |
2 |
— | — | — | 2 |
BREAKING / FAIL |
4 |
4 |
4 |
— | 4 |
— | 1 |
| Missing symbols | — | — | — | — | — | 2 |
— |
| Load failure | — | — | — | 1 |
4 |
— | — |
| Tool error | 2† |
2† |
1 |
— | — | 1 |
3/4/5/6/7/8/10/11 |
* Severity exit codes depend on the configuration. For example, with
--severity-addition error, additions exit 1; with --severity-preset
info-only, everything exits 0.
† Click uses exit code 2 for argument/usage errors. To reliably distinguish
verdicts from tool errors, use --format json and read the verdict field.
Strict mode (-s / -strict)¶
compat (and only compat) supports strict mode to promote lesser verdicts:
# Strict mode: COMPATIBLE + API_BREAK → exit 1 (BREAKING)
abicheck compat -lib foo -old OLD.xml -new NEW.xml -s
# Strict API-only: only API_BREAK → exit 1; COMPATIBLE stays exit 0
abicheck compat -lib foo -old OLD.xml -new NEW.xml -s --strict-mode api
--strict-mode values:
- full (default when -s is set): COMPATIBLE + API_BREAK → BREAKING
- api: only API_BREAK → BREAKING; COMPATIBLE unchanged
--strict-mode has no effect unless -s is also passed.
Note:
abicheck comparedoes not have-s/--strictflags. For compare-mode strict pipelines, use CI exit code logic (check exit2as a failure).