Model files and cache
Where candding looks for weights, which files it downloads and reads, how gated repositories work and how to use a local directory.
candding reads and writes the Hugging Face cache layout that the hf CLI and the Python libraries use, so a model already pulled for another tool loads with no request to the Hub. A local directory can stand in for a model id anywhere one is accepted.
Cache layout
The root is the first of $HF_HUB_CACHE, the older $HUGGINGFACE_HUB_CACHE, $HF_HOME/hub, $XDG_CACHE_HOME/huggingface/hub and ~/.cache/huggingface/hub, in huggingface_hub's order and with its expansion of ~, $VAR and ${VAR}.
~/.cache/huggingface/hub/
models--BAAI--bge-small-en-v1.5/
refs/main one line: the commit hash the branch points at
snapshots/<hash>/ config.json, tokenizer.json, model.safetensors
blobs/ the file contents the snapshot entries link to
.candding/locks/models--BAAI--bge-small-en-v1.5.lock
held while a fetch of the model runs
.candding/in-progress/models--BAAI--bge-small-en-v1.5/<hash>
present only while a fetch writes that commit- A repository id becomes a directory name with each slash replaced by a double dash.
- The builder's
revision,mainby default, takes a branch, a tag or a commit hash; a revision with no file underrefs/is read as a hash. - A snapshot loads with no request unless
.candding/in-progress/names its commit, which marks a fetch that did not finish.
What gets downloaded
With the default download feature, a missing snapshot is fetched in Rust, with only the files that *.json, *.safetensors, 1_Pooling/* and *_Dense/* select, matched against the whole relative path as huggingface_hub matches them, so *.json also reaches 1_SpladePooling/config.json. ONNX exports, GGUF files, OpenVINO directories and PyTorch .bin checkpoints are skipped when the repository publishes safetensors.
| Guarantee | How |
|---|---|
| An interrupted download never passes for a complete snapshot | .candding/in-progress/ names the commit until the last file lands, and a branch or tag's refs/ file is written after it; the next build or fetch of that revision completes it |
| An error page never becomes a model file | each file is checked against the listing's size and, for a file git stores itself rather than LFS, its git blob id; a mismatch is CanddingError::DownloadFailed, and nothing of it is kept |
| No answer from the Hub chooses where a file lands | a blob is named by the hash candding computes, and a listed path that would leave the snapshot directory, or a malformed commit, is refused before any download |
| Two fetches of one model do not interleave | a fetch holds an exclusive lock on .candding/locks/<repository>.lock until its last write; a second fetch waits, then finds the files in place |
When the Hub answers that a file is stored with Xet, hf-hub fetches it through hf-xet, which acts on the storage address the endpoint gives it; set HF_ENDPOINT only to a hub you trust.
BAAI/bge-m3 and prithivida/Splade_PP_en_v1 publish no safetensors, so their registry entries declare the pickle format and the fetch adds pytorch_model.bin for them alone. A pickle-only repository outside the catalog is fetched without its weights, and its CanddingError::MissingWeights names the file to put into the snapshot directory.
| Failure | Error |
|---|---|
a 401 or 403 on a file, or the Hub's GatedRepo code | CanddingError::GatedModel |
| the repository does not exist, or is private and the request carries no token | CanddingError::RepositoryNotFound |
| the revision does not exist | CanddingError::RevisionNotFound |
| the Hub cannot be reached | CanddingError::Network |
| an unsafe path or commit in the listing | CanddingError::UnsafeHubPath |
| any other answer from the Hub | CanddingError::DownloadFailed |
HF_HUB_OFFLINE is set and the cache lacks the snapshot | CanddingError::Offline |
HF_HUB_OFFLINE takes 1, ON, YES or TRUE; a cached snapshot still loads and nothing touches the network. Built with default-features = false, candding reads only the cache and local directories, and a missing model is CanddingError::ModelNotFound, whose message names the download feature and the candding fetch command that fills the cache.
What the loader reads
| File | Required | What it decides |
|---|---|---|
config.json | yes | model_type selects the family; pad_token_id sets the padding token when present |
tokenizer.json | yes | the tokenizer, replayed as published |
model.safetensors | yes, or an index | the weights, memory-mapped |
model.safetensors.index.json | when the weights are sharded | the shards, loaded in name order |
pytorch_model.bin | when there is neither a model.safetensors nor an index | the weights, read out of the torch zip |
1_Pooling/config.json | no | pooling for a repository with no registry entry and no descriptor |
tokenizer_config.json | no | the padding token when config.json has no pad_token_id; without either, the padding id is zero |
modules.json | no | the Dense directories; a module type the pipeline does not run is refused, and Normalize changes nothing |
{n}_Dense/config.json, {n}_Dense/model.safetensors | when modules.json lists them | the linear layers after pooling, in F32 |
- A registry model, or one given a descriptor, takes pooling, normalization, templates and dimension from the descriptor; Dense directories that differ from what
modules.jsonlists fail withCanddingError::DenseMismatch. - The weights are cast on the CPU to the requested dtype and moved to the device one tensor at a time, so the device holds only the finished copy.
- Before any tensor is read, a missing
config.jsonortokenizer.jsonisCanddingError::MissingFilewith the expected path, and a directory with no weights isCanddingError::MissingWeights, which names every file it looked for.
Gated models
A gated repository needs its licence accepted on huggingface.co and a token from HF_TOKEN, the file HF_TOKEN_PATH names, or token under HF_HOME; HF_HUB_DISABLE_IMPLICIT_TOKEN keeps the environment's token from being sent. Without access, the first download fails with CanddingError::GatedModel, which a retry cannot fix. EmbeddingGemma is the catalog's only gated model.
Local directories
An existing directory is accepted anywhere a model id is, without consulting the cache, and needs what a snapshot holds: config.json, tokenizer.json and the weights. A path that does not exist is tried as a repository id, so a typo surfaces as RepositoryNotFound, or as ModelNotFound without the download feature; a spec that is not a valid id, such as ./models/name, is refused before any request.
Devices and dtypes
How candding picks CPU, Metal or CUDA, which dtypes each device runs, where the only backend branch lives, and the backend features.
Sparse output
What a sparse embedding is, what each of the six sparse heads indexes and computes, how two rows are scored, and which dtypes each head supports.