Skip to content
Latchkey

mypy "--strict" Stale Cache Causes Phantom Errors in CI

mypy caches per-module results in .mypy_cache. Under --strict, a cache restored from a different mypy version, Python version, or config can produce inconsistent or phantom errors that vanish after the cache is cleared.

What this error means

mypy --strict fails in CI with errors that do not reproduce locally, or that disappear when .mypy_cache is deleted. A cached CI run after a mypy/config bump reports stale results that no longer match the source.

mypy output
app/models.py:12: error: Returning Any from function declared to return "int"
# ...but the code is correct; a cache from an older mypy/config is being reused

Common causes

Cache restored across version/config changes

A CI cache key that ignores the mypy version, Python version, or config hash restores a .mypy_cache that no longer matches the current strictness/settings.

Partial or corrupted cache

An interrupted run or a cache shared between incompatible environments leaves inconsistent per-module data that yields phantom errors.

How to fix it

Key the cache on tool and config versions

Include the mypy version, Python version, and config hash in the cache key so a change invalidates it.

.github/workflows/ci.yml
- uses: actions/cache@v4
  with:
    path: .mypy_cache
    key: mypy-${{ hashFiles('pyproject.toml') }}-py${{ matrix.python-version }}

Clear the cache to confirm the real result

When errors look wrong, run without the cache to get the authoritative result.

Terminal
mypy --strict --no-incremental .
# or remove it
rm -rf .mypy_cache && mypy --strict .

How to prevent it

  • Include mypy/Python/config in the .mypy_cache cache key.
  • Use --no-incremental in CI when cache correctness is uncertain.
  • Pin mypy so strictness behavior is stable across runs.

Related guides

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