Skip to content

fix(hub): link ranged weight downloads into the HF snapshot dir - #56

Open
matts-path wants to merge 1 commit into
basecompute:mainfrom
matts-path:fix/pull-weight-symlink-missing
Open

fix(hub): link ranged weight downloads into the HF snapshot dir#56
matts-path wants to merge 1 commit into
basecompute:mainfrom
matts-path:fix/pull-weight-symlink-missing

Conversation

@matts-path

Copy link
Copy Markdown

Fixes #54.

Problem

basert pull <org>/<model> (raw HF convert-on-pull, not the basecompute/<name> catalog path) reliably downloads weight shards in full but fails conversion with No such file or directory opening a .safetensors file — and a retry can't self-heal.

Root cause

HfFetcher::get_file's ranged/resumable branch (base-convert/crates/base-hub/src/fetch.rs), used for any file ≥RANGED_MIN_BYTES (32MiB — i.e. the weight shards), returns a raw blobs/<hash> path. Unlike the small-file branch, which delegates to hf-hub's own single-stream download and gets its snapshots/<rev>/<filename> symlink for free, the ranged branch never creates one.

download_source (base-convert/crates/base-convert/src/hub.rs) trusted this: it anchors the snapshot dir on config.json's parent, then calls fetcher.get_file for every other wanted file and discards the returned path, assuming it landed beside config.json. For a weight shard that assumption is false — the blob sits in blobs/, never linked into the snapshot dir download_source just promised was complete. Conversion then reads from that (missing) snapshot path and fails.

Retrying doesn't help either: the "already downloaded" check for ranged files only compares blob byte-length, so pull (with or without --force) just reconfirms the blob is present and proceeds straight to the same failure.

Full repro details, byte-level verification, and file:line references are in #54.

Fix

download_source now checks, for every fetched file, whether it already resolves where the snapshot dir expects it — and if not (the ranged-download case), links it in itself (link_into_snapshot). This is a no-op for anything that was already placed correctly (small files, and every existing test double), and it also makes a partially-broken cache self-healing on the next pull, since it runs unconditionally rather than depending on a fresh download happening.

Testing

  • cargo build / cargo test / cargo clippy clean for base-convert and base-hub (45 + 44 tests passing).
  • Added download_source_links_ranged_weight_into_snapshot: a new RangedFetcher test double that reproduces the actual split (weight file returns a raw blob path; metadata files already symlinked) — the existing StagedFetcher double pre-stages symlinks for every file and so never exercised this path, which is how the bug shipped uncaught.
  • End-to-end: deleted a full Qwen/Qwen3-0.6B cache entry and re-ran basert pull Qwen/Qwen3-0.6B from scratch with the patched binary — succeeded in one shot with no manual intervention, where it reliably failed before this change.

Opening as a draft for review — happy to adjust naming/placement of link_into_snapshot or add coverage elsewhere if there's a preferred spot.

HfFetcher::get_file's ranged/resumable branch (used for any file
>=32MiB, i.e. the weight shards) returns a raw blobs/<hash> path and
never creates the snapshots/<rev>/<filename> symlink that hf-hub's
own single-stream download creates for small files. download_source
discarded that return value and assumed every wanted file landed
beside config.json, so a convert-on-pull of a raw HF repo (org/model,
not the basecompute catalog) reliably downloaded the weight blob in
full but failed conversion with "No such file or directory" opening
it from the snapshot dir — and retrying couldn't self-heal, since the
"already downloaded" check only compares blob size.

download_source now links each fetched file into the snapshot dir
itself when the fetcher didn't already place it there, which also
makes a retry over a partially-broken cache self-healing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@matts-path
matts-path marked this pull request as ready for review August 20, 2026 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pull: weight-file symlink never created for large HF downloads (ranged path), leaves cache permanently broken

1 participant