You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Ruff fix functions return successful Changesets after Ruff exits with a usage error #99
At b0e9d0ca81328d3c91a08ab8c7a0e8963c2fa7ae, both RuffChecker.fix and RuffFormatter.fix suppress nonzero Ruff execution and return a Changeset.
Expected behavior
An auto-fix call must fail when Ruff itself fails with a usage, configuration, or runtime error. Normal lint/fix findings are distinct from Ruff process failure.
Actual behavior
Both methods use expect=dagger.ReturnType.ANY, await only combined output, print the error, and construct a Changeset without checking the exit status.
Observed: both RED cases fail with Failed: DID NOT RAISE after Ruff's error: unexpected argument '--definitely-invalid' output. Independent Ruff 0.16.0 probes return exit 2 for the same invalid commands.
The paired exit-0 controls return Changesets successfully.
Impact
Misspelled or unsupported extra_args, invalid configuration, and Ruff runtime failures can look like successful auto-fix operations, potentially yielding empty or partial Changesets.
Root cause
ruff/src/ruff/checker.py:57-64
ruff/src/ruff/formatter.py:57-64
Both opt out of Dagger's default fail-closed process handling and never restore an exit-status check.
Suggested fix and regression test
Use normal fail-closed execution, or explicitly inspect and reject nonzero status before constructing the Changeset. Parameterize checker/formatter with exit 2 and exit 0 controls.
Duplicate check
The complete tracker, comments, reviews, timelines, and open patches were inspected. Fresh searches covered exact error text, both class methods, ReturnType.ANY, exit 2, failure suppression, and fail-closed synonyms. PRs #34, #36, and #38 are adjacent generator/exit-code history but do not mention or fix this Ruff behavior.
expect=dagger.ReturnType.ANY was introduced so that ruff check --fix does not fail Dagger's execution when unfixable lint violations remain (which Ruff signals via exit code 1 while still applying auto-fixes to disk).
However, Ruff adheres to standard CLI conventions:
Exit 0: Success (clean / all fixes applied).
Exit 1: Lint violations remain (only possible in check).
Similarly, ruff format (without --check) succeeds on exit 0; any non-zero exit code represents a failure.
By omitting an explicit exit code check after result = ctr.with_exec(..., expect=dagger.ReturnType.ANY), exit code 2 errors were suppressed and resulted in false-success Changeset objects.
Activity
aoright commentedon Sep 24, 2026
I implemented and verified a targeted fix for this issue on fork branch
fix/ruff-fix-exit-code(commitac3baf0).Compare: main...aoright:daggerverse:fix/ruff-fix-exit-code
1. Root Cause & Ruff Exit Code Semantics
expect=dagger.ReturnType.ANYwas introduced so thatruff check --fixdoes not fail Dagger's execution when unfixable lint violations remain (which Ruff signals via exit code 1 while still applying auto-fixes to disk).check).extra_args), invalid configuration, syntax parsing crashes, or internal runtime failure.ruff format(without--check) succeeds on exit 0; any non-zero exit code represents a failure.result = ctr.with_exec(..., expect=dagger.ReturnType.ANY), exit code 2 errors were suppressed and resulted in false-successChangesetobjects.2. Implementation
In
ruff/src/ruff/checker.py:In
ruff/src/ruff/formatter.py:Verified with
ruff checkandruff format(0 findings).aoright commentedon Sep 24, 2026
Opened PR #106 with the zero-regression fix and test coverage.