Originally created by: Akarsh-Hegde
A first-run model prefetch wedged at 57% for 4+ hours on a healthy 16 Mbps link (the bar froze, bytes never resumed).
Root cause: hf_xet does its transfer in Rust with no per-read timeout and can't be interrupted from Python. When a connection to the Xet CAS endpoint goes half-open (stops sending bytes but never errors — e.g. a firewall/proxy/regional block on *.xethub.hf.co), snapshot_download blocks the download thread forever: prefetch_state stays downloading and the wizard bar sits at the last byte count indefinitely.
services/agents/routes/prefetch.py, _download_spec)huggingface_hub's module constant (HF_HUB_DISABLE_XET) — not the env var, which is parsed once at import. This forces the classic LFS path, which caps every read at HF_HUB_DOWNLOAD_TIMEOUT (10s) and resumes from the .incomplete partial via a Range request, so a stall raises and self-heals instead of hanging.MERIDIAN_PREFETCH_MAX_ATTEMPTS overridable). Each retry resumes from disk, so transient drops converge without re-pulling.A/B on the same model showed Xet-on == Xet-off == network ceiling (no benefit on a cold first-run pull of distinct weights — chunk-dedup buys little), while parallel range requests did not beat a single stream (link-bound, not per-connection-throttled). So this trades an unused fast-path for a bounded, resumable one.
Bonus: the classic path grows the on-disk blob linearly, so /prefetch_status's byte-delta speed reads smoothly instead of sitting at 0 then bursting as hf_xet flushed reconstructed chunks (fixes the frozen-looking bar).
Full 3-model prefetch (~2.46 GB) completed in ~11 min at the link ceiling with smooth progress and no hang. A mid-download stall (dropped to ~1 MB/s for ~90s) recovered on its own instead of wedging — exactly the timeout+resume behavior intended.
fix/prefetch-speed-state-lint (PR [#348], closed) — re-homed here on a fresh branch off pre-main so it can actually land.🤖 Generated with Claude Code
Originally posted by: coderabbitai[bot]
✨ Finishing Touches
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests - [ ] Commit unit tests in branch `fix/prefetch-xet-hang`Comment
@coderabbitai helpto get the list of available commands.Originally posted by: Akarsh-Hegde
Fixes pushed (
4f4b944c)Resolved both findings from the review above:
✅ 1. Startup-crash on bad env value — fixed
Replaced the bare
int(os.environ.get(...))with a defensive helper:Verified:
MERIDIAN_PREFETCH_MAX_ATTEMPTS=oopsnow logs a warning and falls back to5instead of raising at import; a valid=3is still respected.✅ 2.
assert-guarded raise — fixedDropped
last_excand theassertentirely; the loop re-raises the active exception with a bareraiseon the final attempt:Now
-O-safe (no assert) and the exhaustion path is unconditional.Not changed (intentional, per review notes [#3] & [#4])
except Exceptionretry — kept for resilience to backend-specific stall exceptions; backoff caps waste at ~30s.No behavioural change to the happy path or the hang fix. Pre-commit/pre-push checks pass.
Related
Tickets:
#3Tickets:
#4Ticket changed by: Akarsh-Hegde