Field note · llama.cpp

Downloading one new file from a Hugging Face repo invalidates the path to all the others

Fetching a newly published mmproj moved refs/main to a fresh snapshot directory containing only that one file, while 93.6 GB of weights stayed in the previous snapshot. Any launcher resolving through refs/main — which is the recommended practice, since snapshot hashes change on every re-pull — then fails its own existence check on weights that are plainly on disk. The fix downloads nothing: a second hf download with the original include pattern relinks the existing blobs into the current snapshot.

Hardware
NVIDIA DGX Spark · GB10 (SM121) · aarch64 · 128 GB unified
Software
huggingface_hub CLI · unsloth/Qwen3.8-Flash-Next-GGUF UD-IQ4_XS (93.6 GB, 3 shards) + mmproj-F16.gguf

What happened

The vendor published a vision projector a day after the weights. Fetching just that one file:

hf download unsloth/Qwen3.8-Flash-Next-GGUF --include 'mmproj-F16.gguf'

left the cache looking like this:

snapshots/178b9988.../     <- refs/main now points here
  mmproj-F16.gguf          <- and nothing else
snapshots/8bdc6666.../     <- the 93.6 GB of weights are still over here
  UD-IQ4_XS/...

The start script resolves the model path through refs/main, which is the correct practice — snapshot hashes change on every re-pull, so hardcoding one guarantees a stale path later. It then failed its own preflight existence check on 93.6 GB of weights that had never moved and were sitting on the same disk.

The fix downloads nothing

Re-run the original include pattern. Hugging Face hard-links the blobs it already has into the current snapshot directory:

hf download unsloth/Qwen3.8-Flash-Next-GGUF --include '*UD-IQ4_XS*'

Repo size stayed at 89 GB. No bytes crossed the network. The snapshot directory simply gained links to the blobs it was missing.

The general shape

A snapshot is a view of one fetch, not of the repository. It contains links only to the files that fetch asked for. So the invariant most launchers assume — "refs/main names a directory containing everything I have downloaded" — is false the moment you do a second partial download.

Two habits that hold:

  • After any partial hf download, re-run every other include pattern you depend on. It is cheap and idempotent.
  • Have the preflight report the resolved path, not just pass or fail. "Weights not found" sent me looking at disk space and permissions. "Weights not found at snapshots/178b9988.../UD-IQ4_XS/" would have ended it immediately, because the hash was visibly the wrong one.

Enabling the projector itself cost less than expected — about 1 GiB resident, no llama.cpp changes at all (it reuses the existing qwen3vl_merger projector type), and it does not affect prefix caching, which matters on a prefill-bound workload where losing that would have cost far more than the memory. It does force-disable --ctx-shift whenever an mmproj is loaded.

Status
resolved
First seen
August 28, 2026