Skip to content

ADR-0006 — Don't pin mypy's python_version when checking across a matrix

Context

[tool.mypy] pinned python_version = "3.11", matching the project's minimum supported version. CI's mypy step passed locally (Python 3.11) but failed in GitHub Actions on the 3.12 and 3.13 jobs with:

.venv/lib/python3.13/site-packages/numpy/__init__.pyi:737: error:
Type statement is only supported in Python 3.12 and greater  [syntax]

numpy is a transitive dependency (via chromadb, used lazily in stores/chroma.py) — not imported directly anywhere in this codebase. uv resolves a different numpy release per Python target (2.4.6 for 3.11, 2.5.3 for 3.13 in this case), and the 3.13-targeted release ships a .pyi stub using a PEP 695 type alias statement, which is syntax only valid from Python 3.12 onward. Pinning mypy's target to 3.11 made it parse every file it touched — including that stub — with pre-3.12 grammar, which is a hard syntax error, not a typing warning ignore_missing_imports could suppress.

Decision

Remove the python_version pin entirely. Left unset, mypy defaults to the version of the interpreter actually running it, which is exactly the Python version uv resolved that job's dependencies for — the mismatch disappears structurally instead of needing a per-dependency workaround.

Consequences

  • Verified locally against all three supported versions (3.11, 3.12, 3.13) before pushing the fix, rather than trusting a single local run — this bug specifically couldn't have been caught by mypy under 3.11 alone.
  • A future dependency could reintroduce a similar mismatch in the other direction (a stub requiring syntax older than some job's target wouldn't happen — newer syntax is the only failure mode this way). Nothing currently guards against that beyond CI's matrix itself surfacing it again, which is an acceptable trade-off given how narrow the failure mode is.

What would invalidate this

If the project ever needs to assert "this code must type-check as valid Python 3.11" as a real constraint (not just "the library must run on 3.11"), that check belongs in a dedicated, single-version CI job with its own python_version override — not as the default for every job in the matrix.