ruff 0.15 -> 0.17 flags hundreds of new errors with no config change (B008 on FastAPI Depends defaults, UP007, I001, BLE001...)
Observed (2026-10, yap.so repo, ruff check ysrv yap with only [tool.ruff] target-version = "py312" in config):
uvx ruff@0.15.1 check-> All checks passed!uvx ruff@0.17.0 check-> Found 722 errors.--statistics: 252 B008 function-call-in-default-argument, 135 UP007, 98 I001, 53 UP035, 45 UP017, 33 RUF012, 31 BLE001, plus PLW1510, ISC004, RUF059, PLR1711, UP037, C408, FURB167, FLY002.ruff format --checkwas unaffected (no reformat).
So a project relying on ruff's implicit default rule set picks up flake8-bugbear, pyupgrade, isort, ruff-specific, blind-except and pylint rules on the bump. In a pre-commit hook pinned via rev: the hook fails on the next touched file; with unpinned ruff in CI, every PR breaks.
Options:
- Keep the old behavior explicitly, then bump:
[tool.ruff.lint] select = ["E4", "E7", "E9", "F"]. - Adopt the new rules:
ruff check --fixtakes the ~half that are autofixable; for FastAPI, B008 is a false positive on dependency-injection defaults, so add[tool.ruff.lint.flake8-bugbear] extend-immutable-calls = ["fastapi.Depends", "fastapi.Query", "fastapi.Body", "fastapi.Header", "fastapi.Cookie", "fastapi.File", "fastapi.Form", "fastapi.Path", "fastapi.Security"].
Check before bumping: uvx ruff@<new> check <paths> --statistics against the current tree; compare to the pinned version's output.
Observed (2026-10, yap.so repo, ruff check ysrv yap with only [tool.ruff] target-version = "py312" in config):
uvx ruff@0.15.1 check-> All checks passed!uvx ruff@0.17.0 check-> Found 722 errors.--statistics: 252 B008 function-call-in-default-argument, 135 UP007, 98 I001, 53 UP035, 45 UP017, 33 RUF012, 31 BLE001, plus PLW1510, ISC004, RUF059, PLR1711, UP037, C408, FURB167, FLY002.ruff format --checkwas unaffected (no reformat).
So a project relying on ruff's implicit default rule set picks up flake8-bugbear, pyupgrade, isort, ruff-specific, blind-except and pylint rules on the bump. In a pre-commit hook pinned via rev: the hook fails on the next touched file; with unpinned ruff in CI, every PR breaks.
Options:
- Keep the old behavior explicitly, then bump:
[tool.ruff.lint] select = ["E4", "E7", "E9", "F"]. - Adopt the new rules:
ruff check --fixtakes the ~half that are autofixable; for FastAPI, B008 is a false positive on dependency-injection defaults, so add[tool.ruff.lint.flake8-bugbear] extend-immutable-calls = ["fastapi.Depends", "fastapi.Query", "fastapi.Body", "fastapi.Header", "fastapi.Cookie", "fastapi.File", "fastapi.Form", "fastapi.Path", "fastapi.Security"].
Check before bumping: uvx ruff@<new> check <paths> --statistics against the current tree; compare to the pinned version's output.