candding
Concepts

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, main by default, takes a branch, a tag or a commit hash; a revision with no file under refs/ 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.

GuaranteeHow
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 fileeach 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 landsa 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 interleavea 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.

FailureError
a 401 or 403 on a file, or the Hub's GatedRepo codeCanddingError::GatedModel
the repository does not exist, or is private and the request carries no tokenCanddingError::RepositoryNotFound
the revision does not existCanddingError::RevisionNotFound
the Hub cannot be reachedCanddingError::Network
an unsafe path or commit in the listingCanddingError::UnsafeHubPath
any other answer from the HubCanddingError::DownloadFailed
HF_HUB_OFFLINE is set and the cache lacks the snapshotCanddingError::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

FileRequiredWhat it decides
config.jsonyesmodel_type selects the family; pad_token_id sets the padding token when present
tokenizer.jsonyesthe tokenizer, replayed as published
model.safetensorsyes, or an indexthe weights, memory-mapped
model.safetensors.index.jsonwhen the weights are shardedthe shards, loaded in name order
pytorch_model.binwhen there is neither a model.safetensors nor an indexthe weights, read out of the torch zip
1_Pooling/config.jsonnopooling for a repository with no registry entry and no descriptor
tokenizer_config.jsonnothe padding token when config.json has no pad_token_id; without either, the padding id is zero
modules.jsonnothe Dense directories; a module type the pipeline does not run is refused, and Normalize changes nothing
{n}_Dense/config.json, {n}_Dense/model.safetensorswhen modules.json lists themthe 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.json lists fail with CanddingError::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.json or tokenizer.json is CanddingError::MissingFile with the expected path, and a directory with no weights is CanddingError::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.

On this page