Exit codes¶
Pyfaro distinguishes its own failures from the failures of the tools it runs. These exit codes are a stable contract for the public beta: scripts and CI can rely on them, and a change is a breaking change announced in the changelog. Message wording is not part of the contract.
| Code | Meaning |
|---|---|
0 |
Success. Also --help, --version, and a doctor report with warnings only. |
1 |
A Pyfaro failure, a failing check, a doctor report with an ERROR, or a tool that ended without a numeric exit status. |
2 |
Invalid usage: an unknown flag, a missing argument, pyfaro run with nothing to run. |
| tool's code | The delegated tool's own exit code, forwarded unchanged. |
130 |
Cancelled with Ctrl+C. |
Pyfaro's own diagnostics go to standard error: error: ... for failures and
pyfaro <command>: ... lines for dev, --verbose
and notes. Reports that are a command's output, such as doctor and tools,
stay on standard output. Child processes write where they always do and Pyfaro
does not rewrite their output.
Pyfaro's own failures: 1¶
Exit code 1 covers problems Pyfaro detects before or around running a tool:
no project found, invalid [tool.pyfaro], uv missing or too old, a tool not
found, a command that cannot be started.
A tool that ends without a numeric status (killed by a signal, for instance)
also gives 1, with a diagnostic such as error: ruff failed (signal: 9
(SIGKILL)). A program killed by a signal inside pyfaro run is different:
uv reports it as 128 + signal (137 for SIGKILL) and that number is
forwarded.
Usage errors: 2¶
Invalid command-line usage exits with 2. That covers Clap's errors (unknown
flags and subcommands, missing arguments, conflicting options, no arguments at
all) and the commands Pyfaro cannot act on, such as pyfaro run with neither a
task nor -- <program>:
Forwarded codes¶
When a command runs a single tool, the tool's code is the command's code. This holds for:
| Command | Code returned |
|---|---|
sync, build, add, remove, python |
uv's |
init --apply |
uv's |
run (a program or a task) |
the program's, through uv run |
dev |
the process's, through uv run |
lint, fmt, type |
Ruff's or ty's |
test |
pytest's |
For example:
$ pyfaro test -k nomatch
...
============================ 1 deselected in 0.01s =============================
error: pytest failed (exit status: 5); see pytest's output above
$ echo $?
5
pytest's codes keep their meaning (1 failures, 2 interrupted, 5 no tests
collected, and so on), so scripts can tell them apart. A failed forwarded
command prints error: <tool> failed (<status>); see <tool>'s output above
after the tool's own output. If uv --version itself fails, the commands that
use uv return uv's status for that probe; an unsupported uv version is a
Pyfaro failure (1).
A forwarded code can be 2 too
Because the tool's code is forwarded, 2 can also be uv's or pytest's own
code. The error: line says which tool failed.
check: aggregate 1¶
pyfaro check runs three steps, the format check, lint and type check, and
runs all of them even if one fails. It exits 1 if any step failed,
whatever codes the tools returned, and 0 otherwise. The summary lists what
failed:
$ pyfaro check
...
== pyfaro check summary ==
format: failed (exit 1)
lint: failed (exit 1)
type: failed (exit 1)
check: failed (format, lint, type)
doctor and tools¶
doctorexits 1 if it reports anyERROR. Warnings alone leave it at 0. A tool version probe that fails is a finding, not a forwarded code.pyfaro toolslists tools and exits 0. With a tool name, as inpyfaro tools ruff, a missing or broken tool is an error with exit 1.
dev: the process's own code¶
pyfaro dev runs a long-lived process. If it exits with status N, Pyfaro
prints pyfaro dev: <runner> exited with status N and exits N; exit 0 is
silent. Ctrl+C prints pyfaro dev: stopped and exits 130. See
pyfaro dev.
Cancellation: 130¶
On Ctrl+C, Pyfaro stops the process tree it started, waits for it to
exit, and returns 130 (error: operation cancelled, or pyfaro dev: stopped
for dev). If cleanup cannot be confirmed, it reports an error and exits 1.
Next steps¶
- Troubleshooting shows
--verbose, which prints the tool versions and commands behind a failure. - Continuous integration shows how to use these codes in a pipeline.
- The quality gate.