Skip to content
Latchkey

ruff Version Drift Fails CI With New Lint Rules

ruff ships new lint rules and tightens existing ones across releases. An unpinned ruff that upgrades between runs can suddenly flag code that passed yesterday - a tooling-version change, not a code change.

What this error means

CI lint fails on rules that were not failing before, with no relevant code change. Comparing ruff --version between the passing and failing runs shows a bump; pinning the old version makes the failures disappear.

ruff output
app/main.py:12:1: UP045 Use `X | None` instead of `Optional[X]`
Found 7 errors.
# ruff upgraded 0.5.x -> 0.6.x and enabled or changed rules

Common causes

Unpinned ruff upgraded between runs

Without a pinned version (in requirements/pre-commit), CI installs the latest ruff. A new release’s added or stricter rules flag previously-clean code.

Target version or rule selection drifted

A changed default rule set, or a target-version mismatch, changes which lints apply across ruff releases.

How to fix it

Pin ruff and upgrade deliberately

Pin the exact version in CI and pre-commit so upgrades are intentional and reviewable.

config
# requirements-dev.txt
ruff==0.6.9
# .pre-commit-config.yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
  rev: v0.6.9

Adopt new rules on your terms

When you do upgrade, fix or explicitly select/ignore the new rules rather than letting them fail silently.

Terminal / pyproject.toml
ruff check --fix .
# pin rule selection in config
[tool.ruff.lint]
select = ["E", "F", "UP"]

How to prevent it

  • Pin ruff’s exact version in CI and pre-commit.
  • Bump the version in a dedicated change so new rules are reviewed.
  • Pin select/target-version so rule sets are explicit.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →