Flintstack › Troubleshooting
Troubleshooting
Symptom, cause, and the one command that confirms it before you touch anything.
Symptoms first, in the order they arrive by mail. Each one names the command that confirms the cause before you change anything - a cache is the wrong place to fix a problem by guessing. If none of these fit, the FAQ covers the questions that are not failures, and the CLI reference has the exit codes in full.
The hit rate sits at zero
A store that fills but never matches means the key is changing between otherwise identical builds. Run flint key --explain on two consecutive invocations and diff the output: the usual culprits are an absolute path that leaked into the argument vector, a build timestamp that was never on the allowlist, and include_mtime = true turning a touch into an invalidation. Fix the input, not the cache.
The disk fills up
Either eviction is off or the store is growing faster than it can reclaim. Check flint stats against max_size; if the store is below the ceiling and the disk is still full, something outside the store root is the problem. If it is at the ceiling and climbing, you are almost certainly writing unmatched entries - see the zero-hit case above - and the real fix is reproducibility, not a bigger max_size.
Builds got slower with the cache on
On a genuinely cold shared cache, every lookup pays one round trip before the compiler starts, and that overhead is real. Set timeout = "1s" on remote backends you do not trust, or run with --no-store on a machine that should only read. If a local-only store is slower, the disk holding it is the suspect; turn on slow_ms logging and watch for store operations crossing the threshold.
flint wrap says the daemon is unreachable
By design the wrapper then runs the real compiler and exits with its status, so the build still works - slowly. If you want the build to fail instead, pass --require-daemon and branch on exit code 3. Check that flintd is running and that --socket points at the same path on both sides; a stale socket after a crash is removed on the next daemon start.
Exit code 5 from a remote backend
Authentication was rejected. For an objs backend the credentials file must exist, be mode 0600, owned by the daemon user, and name the right bucket and region; for a peer backend the token files on both ends must match byte for byte. The daemon logs which backend rejected it at warning level - read that line before rotating anything.
Exit code 4: store unusable
The store root is locked by another daemon, out of space, or failed the filesystem-semantics check that runs at startup. Only one flintd may own a root at a time; a second one exits 4 rather than corrupt the first. flint doctor prints which of the three it is.
TTL expiry behaves strangely
Age-based expiry uses wall-clock time, so a clock difference between the client and the daemon skews it. Since 0.11.3 flint doctor reports the offset; anything over five minutes is worth fixing with NTP before you distrust the ttl setting.
If normalize_paths is off, the working directory is part of the argument vector and two checkouts in different directories compute different keys. Turn it back on - it is the default - and confirm with flint key --explain that the output path has been normalized away in both trees.
Still stuck? Mail dev@flintstack.dev with the
output of flint doctor and one flint key --explain from a build that
missed when you expected a hit. Those two outputs answer most of what we would ask back.
Last updated: 2026-09-29