headroomlabs-ai/headroom · error · ValueError
pyproject.toml must contain one exact Ruff pin in project.op
Error message
pyproject.toml must contain one exact Ruff pin in project.optional-dependencies.dev
What it means
After finding the single Ruff dev dependency, verify-ruff-version.py requires it to be an exact pin matching `ruff==<version>` exactly (fullmatch, no range, no extras, no environment markers). Loose constraints like `ruff>=0.4` or `ruff` break the invariant that pyproject.toml is the single source of truth for the Ruff version.
Source
Thrown at scripts/verify-ruff-version.py:37
WORKFLOW_INSTALL_REFERENCE = "steps.ruff-version.outputs.version"
def _load_toml(path: Path) -> dict[str, Any]:
with path.open("rb") as file:
return cast(dict[str, Any], tomllib.load(file))
def _authoritative_version() -> str:
dependencies = _load_toml(ROOT / "pyproject.toml")["project"]["optional-dependencies"]["dev"]
ruff_requirements = [
requirement for requirement in dependencies if requirement.startswith("ruff")
]
if len(ruff_requirements) != 1:
raise ValueError(f"expected one Ruff dev dependency, found {ruff_requirements!r}")
match = re.fullmatch(r"ruff==([^;,\s]+)", ruff_requirements[0])
if match is None:
raise ValueError(
"pyproject.toml must contain one exact Ruff pin in project.optional-dependencies.dev"
)
return match.group(1)
def _locked_version() -> str:
packages = _load_toml(ROOT / "uv.lock")["package"]
versions = [str(package["version"]) for package in packages if package["name"] == "ruff"]
if len(versions) != 1:
raise ValueError(f"expected one locked Ruff package, found {versions!r}")
return versions[0]
def _pre_commit_version() -> str:
lines = (ROOT / ".pre-commit-config.yaml").read_text(encoding="utf-8").splitlines()
for index, line in enumerate(lines):
if line.strip() != f"- repo: {RUFF_PRE_COMMIT_REPO}":
continueView on GitHub (pinned to 322425c43b)
Solutions
- Restore the exact pin form: `ruff==X.Y.Z` with no spaces, markers, or extras.
- To upgrade Ruff, change the version on the right of `==` (and let the script verify uv.lock and pre-commit agree).
- Check for stray characters — the fullmatch rejects `ruff == 0.5.0` and `ruff==0.5 ; python_version>='3.9'` alike.
Example fix
# pyproject.toml - before [project.optional-dependencies] dev = ["ruff>=0.5.0"] # after [project.optional-dependencies] dev = ["ruff==0.5.0"]
Defensive patterns
Strategy: validation
Validate before calling
import re
def is_exact_ruff_pin(requirement: str) -> bool:
return re.fullmatch(r"ruff==([^;,\s]+)", requirement) is not None Prevention
- Keep the Ruff dev dependency an exact `ruff==X.Y.Z` string with no markers or spaces.
- Configure dependency bots to keep exact pins (pinning enabled) rather than widening ranges.
- When upgrading Ruff, update pin, uv.lock, and pre-commit rev in one change and run the verify script.
When it happens
Trigger: Changing the pin to `>=`, `~=`, `!=`, or adding a marker/extras to the requirement string; a dependency bot relaxing the pin; hand-merging a conflict resolution that drops the `==`.
Common situations: Renovate/Dependabot range updates replacing `==` with `>=`; developers loosening the pin to test a pre-release; merge conflicts in pyproject.toml.
Related errors
- expected one Ruff dev dependency, found {ruff_requirements!r
- expected one locked Ruff package, found {versions!r}
- could not find a rev for {RUFF_PRE_COMMIT_REPO}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/f0e750be33fe7593.
Report an issue: GitHub.