Skip to content
Latchkey

ruff --exit-zero and --exit-non-zero-on-fix

ruff --exit-zero makes a run always exit 0, and --exit-non-zero-on-fix makes a fixing run fail even when it resolved everything.

Ruff's exit code is the CI gate. These two flags override it for non-blocking runs or for failing when CI had to change files.

What it does

By default ruff check exits 1 if violations remain, 0 if clean, and 2 on error. --exit-zero forces exit 0 regardless, turning a check into an informational run. --exit-non-zero-on-fix exits non-zero when fixes were applied, so a CI step that runs --fix fails if it had to change anything.

Common usage

Terminal
# non-blocking lint (report only, never fail the job)
ruff check --exit-zero .
# fail CI if --fix had to change files
ruff check --fix --exit-non-zero-on-fix .

Flags

FlagWhat it does
--exit-zeroAlways exit 0, even with violations
--exit-non-zero-on-fixExit non-zero if any fix was applied
(default)Exit 1 on violations, 0 clean, 2 on error

In CI

Use --exit-zero only for a deliberately non-blocking, informational job; on a real gate it hides failures. --exit-non-zero-on-fix is the way to make a fixing job fail loudly when code was not pre-formatted, so contributors fix it locally rather than relying on CI to mutate the tree.

Common errors in CI

A lint step that never fails despite obvious violations almost always has --exit-zero left in by accident. Conversely, --exit-non-zero-on-fix failing a build is working as intended: it means --fix changed files, so commit the formatted code. Remember exit 2 (config/parse error) is distinct from exit 1 (violations) and --exit-zero masks both.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →