docir — design documents Graph

Documents / Issues / issue-82b01d7f80d0

CI cached a fastembed directory fastembed stopped writing to

The model cache never hit: the workflow cached ~/.cache/fastembed while fastembed 0.8 writes to $TMPDIR/fastembed_cache, so every run re-downloaded 64MB.

issue-82b01d7f80d0issueresolved#cli#embeddings#testing
View as Markdown◉ View in graph

What was wrong

The workflow cached ~/.cache/fastembed. fastembed 0.8 resolves its cache to tempfile.gettempdir()/fastembed_cache — /tmp/fastembed_cache on a Linux runner — so the key never hit, the post-step had nothing to save, and every run re-downloaded the ~64 MB model while the step's own comment claimed it was downloading them once.

Run 32880647217 says it plainly: Cache not found for input keys: fastembed-Linux-bge-small-en-v1.5, and Post Cache the embedding model took 0s. It had never hit.

~/.cache/fastembed is not an invented path — it is where an older fastembed wrote, and a stale 64 MB copy of the default model still sits there on this machine while the live cache at $TMPDIR/fastembed_cache holds 305 MB. So the workflow was right when it was written and went quietly wrong under an upgrade, which is the same shape as the drift docir's own schema-drift finding exists to report.

The fix

A job-level FASTEMBED_CACHE_PATH pins where the model is written, and the cache step names the same path. Both sides read the literal /tmp/fastembed-cache, so they cannot disagree again.

A literal, and each rejected alternative is its own bug. It may not be ~/.cache/fastembed: a job-level env: value is not shell-expanded, so a literal ~ would have fastembed create a directory actually named ~, while actions/cache does expand ~ in its path: — one side expanding and the other not is how the two came to name different directories in the first place. And it may not be ${{ runner.temp }}/fastembed-cache either, which is what this issue's first fix used: the runner context is unavailable in a job-level env:, which is a workflow-file error, so zero jobs ran and main went red (A workflow context error took main red, and nothing local could have caught it). A literal needs neither rule to be remembered.

Measured locally against a cold directory: 5 files fetched, 64 MB, ~8s; the second run with the same variable set costs 0.93s and fetches nothing.

Since Where a downloaded embedding model lives the variable does more than pin a cache. docir reads it itself and passes it to fastembed as cache_dir, because fastembed computes its temp-directory default before consulting the variable. Unset, the model goes to ~/.docir/models — which on a runner is thrown away with the runner, so the pin is what CI still needs it for.

How it was found

Reading the step timings of the first run of the new reindex -> doctor --strict -> check --strict sequence (issue-87410666c867), because the reindex took 100s rather than the ~70s measured locally. Nothing was failing, and nothing would have started failing — a cache miss only costs time, which is exactly why it survived.

To amend: Re-verify: