Skip to content

Commit 676b142

Browse files
DFlash loader: fail-fast on missing local path instead of silent HF fallback
Surfaces the bug the user hit on Mac mini 2026-06-09: 'failure 原因是默认 DRAFTER_ID=models/dflash-kakeya-baseline 被 当成 HF repo id 去下载,远端返回 404' User ran: SKIP_VERIFIER=1 PROPOSER_KV_CAPTURE=1 \ bash scripts/review_pr_k3_feasibility_on_mac.sh Result: exit_code=25 (fail_at_drafter_load_skip_verifier), JSON evidence shows HF Hub 404 on 'models/dflash-kakeya-baseline'. Root cause: inference_engine.v04.dflash_loader._resolve_local_dir was: def _resolve_local_dir(repo_or_path, hf_kwargs): p = Path(repo_or_path) if p.exists() and p.is_dir(): return p # NB: silent fallthrough — any non-existent local path # gets sent to huggingface_hub.snapshot_download and 404s return Path(snapshot_download(repo_id=repo_or_path, ...)) When the user's Mac mini didn't have 'models/dflash-kakeya-baseline' on disk (likely because 'git lfs pull' hadn't run, or wrong cwd, or worktree without the LFS-tracked checkpoint), the resolver silently treated the path as a HF repo id and got 404 — far from the actual root cause, which was a missing local file. Fix: Add a heuristic _looks_like_local_path() that returns True for inputs starting with 'models/', './', '../', or '/' — the common project- relative or absolute-path prefixes that distinguish a local path from the canonical HF '<user_or_org>/<repo>' format. In _resolve_local_dir, BEFORE falling through to HF Hub fetch: 1. If the input doesn't exist on disk AND looks like a local path per the heuristic → raise FileNotFoundError with an actionable message listing the three common causes (missing 'git lfs pull', wrong cwd, wrong worktree) and how to confirm each. 2. Otherwise (HF-format input not on disk) → continue to HF Hub snapshot_download as before. Pure HF repo ids unaffected. Added regression tests: TestLooksLikeLocalPath (4 tests) - models/* prefix matched - ./ + ../ relative prefixes matched - /Users/... + /tmp/... absolute prefixes matched - HF format (org/repo) NOT matched TestResolveLocalDirFailFast (5 tests) - existing local dir returned as-is - missing 'models/...' raises FileNotFoundError with 'git lfs pull' + 'current working directory' in the message - missing './ ...' / '../...' / '/tmp/...' all raise FileNotFoundError - HF repo id (no local-path prefix) still flows through to huggingface_hub.snapshot_download (verified via monkeypatch) 9/9 new tests pass. 319/319 v04 suite total. Reviewer aid script (scripts/review_pr_k3_feasibility_on_mac.sh) gets a 'pre-flight 0' check that fires BEFORE invoking Python: case "$DRAFTER_ID" in models/*|./*|../*|/*) # if local path doesn't exist on disk → exit 1 with the same # actionable message as the Python-side fail-fast # if exists but missing config.json → exit 1 with file listing esac This means the next user run with the same misconfiguration: - Fails at the bash pre-flight, NOT at HF Hub fetch - Prints the three common causes + recovery commands directly - Doesn't waste time on a 404 round-trip + Python-side error parse Net effect: Two layers of fail-fast (bash pre-flight + Python resolver) catch the 'local path doesn't exist' misconfiguration before it's mis-routed to HF Hub. The user's exact 2026-06-09 failure mode now produces an actionable error in <1 second with three concrete recovery paths, instead of a 404 with 'models/dflash-kakeya-baseline' as a fake repo id. Tests: 319 passed (310 pre-existing + 9 new regression). Stack: same as PR #98 (continuing on the same branch). Scope: this PR's branch is now PR #98 + this fix. The fix is in v0.4 K3 prereq 4 territory (the DFlash loader) and rightfully should backport into PR #95 (K3 Block B prereqs 1+4) when the v04 stack settles. Carrying it on PR #98's branch is the unblock path so the user's next Mac mini run isn't blocked on a missing-local-path 404. Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
1 parent a1263a5 commit 676b142

3 files changed

Lines changed: 183 additions & 1 deletion

File tree

inference_engine/v04/dflash_loader.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,64 @@ def expected_class_name(self) -> str:
143143
)
144144

145145

146+
_LOCAL_PATH_HEURISTICS = (
147+
"models/",
148+
"./",
149+
"../",
150+
"/",
151+
)
152+
153+
154+
def _looks_like_local_path(repo_or_path: str) -> bool:
155+
"""Heuristic: does the input look like a local filesystem path
156+
rather than a HuggingFace ``org/repo`` repo id?
157+
158+
Returns True for inputs starting with ``models/``, ``./``, ``../``,
159+
or ``/`` — the common project-relative or absolute path prefixes.
160+
HF repo ids are ``<user_or_org>/<repo>`` (exactly one slash, no
161+
leading slash, no relative-path component); inputs matching the
162+
HF format return False.
163+
164+
This heuristic is used to **fail fast** when a user passes a
165+
project-relative path (like ``models/dflash-kakeya-baseline``)
166+
that doesn't exist on disk, instead of silently falling through
167+
to HF Hub (which then returns 404 with a confusing error message
168+
far from the actual root cause).
169+
"""
170+
return repo_or_path.startswith(_LOCAL_PATH_HEURISTICS)
171+
172+
146173
def _resolve_local_dir(repo_or_path: str, hf_kwargs: Mapping[str, Any]) -> Path:
147-
"""Resolve repo id to a local snapshot. Pure HF-hub call; no model load."""
174+
"""Resolve repo id to a local snapshot. Pure HF-hub call; no model load.
175+
176+
If ``repo_or_path`` looks like a local path (per
177+
:func:`_looks_like_local_path`) but does NOT exist on disk, this
178+
raises :class:`FileNotFoundError` with an actionable message instead
179+
of silently falling through to ``huggingface_hub.snapshot_download``
180+
(which then emits a 404 error far from the actual root cause —
181+
typically a missing ``git lfs pull`` or wrong cwd).
182+
"""
148183
p = Path(repo_or_path)
149184
if p.exists() and p.is_dir():
150185
return p
186+
if _looks_like_local_path(repo_or_path):
187+
raise FileNotFoundError(
188+
f"DFlash drafter source {repo_or_path!r} looks like a local "
189+
f"path but does not exist on disk (resolved to "
190+
f"{p.absolute()}). Common causes:\n"
191+
f" 1. The Git LFS pointer for the model has not been pulled "
192+
f"yet — run 'git lfs install && git lfs pull' from the repo "
193+
f"root.\n"
194+
f" 2. The current working directory is not the repo root — "
195+
f"verify with 'pwd' and 'ls models/' before re-running.\n"
196+
f" 3. You are on a worktree that does not have the model "
197+
f"checkpoint — use a worktree where 'git lfs pull' has run.\n"
198+
f"\n"
199+
f"If you actually intended a HuggingFace repo id, use the "
200+
f"'<user_or_org>/<repo>' format (no leading 'models/', './' "
201+
f"or '/'). Refusing to silently fall through to HF Hub fetch "
202+
f"because that would 404 with a misleading error message."
203+
)
151204
from huggingface_hub import snapshot_download
152205
cache_dir = hf_kwargs.get("cache_dir")
153206
token = hf_kwargs.get("token") or hf_kwargs.get("use_auth_token")

scripts/review_pr_k3_feasibility_on_mac.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,47 @@ echo " Proposer KV capture: $PROPOSER_KV_CAPTURE"
124124
echo " Report: $report"
125125
echo
126126

127+
# Pre-flight 0: drafter source check (skipped when SKIP_DRAFTER=1).
128+
#
129+
# When DRAFTER_ID is a local path (starts with 'models/', './', '../', '/'),
130+
# verify the directory exists with config.json + safetensors before
131+
# invoking Python — a missing local path otherwise silently falls through
132+
# to HF Hub fetch, which 404s with a misleading error message far from
133+
# the actual root cause (commonly a missing 'git lfs pull' or wrong cwd).
134+
if [[ "$SKIP_DRAFTER" != "1" ]]; then
135+
case "$DRAFTER_ID" in
136+
models/*|./*|../*|/*)
137+
if [[ ! -d "$DRAFTER_ID" ]]; then
138+
echo "ERROR: DRAFTER_ID='$DRAFTER_ID' looks like a local path but does not exist."
139+
echo
140+
echo "Common causes:"
141+
echo " 1. The Git LFS pointer for the model has not been pulled."
142+
echo " Run from the repo root:"
143+
echo " git lfs install"
144+
echo " git lfs pull"
145+
echo
146+
echo " 2. The current working directory is not the repo root."
147+
echo " pwd # should be the repo root"
148+
echo " ls models/ # should list dflash-kakeya-baseline"
149+
echo
150+
echo " 3. You are on a worktree without the model checkpoint."
151+
echo " git status # confirm worktree"
152+
echo
153+
echo "If you intended a HuggingFace repo id instead, override:"
154+
echo " DRAFTER_ID=z-lab/gemma-4-26B-A4B-it-DFlash bash $0"
155+
echo " (note: that variant is NOT alignment-trained — research only)"
156+
exit 1
157+
fi
158+
if [[ ! -f "$DRAFTER_ID/config.json" ]]; then
159+
echo "ERROR: DRAFTER_ID='$DRAFTER_ID' is a directory but lacks config.json."
160+
echo " The model checkpoint at this path is incomplete or corrupted."
161+
ls -la "$DRAFTER_ID" 2>&1 | head -20
162+
exit 1
163+
fi
164+
;;
165+
esac
166+
fi
167+
127168
# Pre-flight 1: quantized verifier exists? (skipped when SKIP_VERIFIER=1)
128169
if [[ "$SKIP_VERIFIER" == "1" ]]; then
129170
echo "[pre-flight] SKIP_VERIFIER=1 set; bypassing verifier-dir check."

tests/inference_engine/v04/test_dflash_loader.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
from inference_engine.v04 import dflash_loader # noqa: E402
3535
from inference_engine.v04.dflash_loader import ( # noqa: E402
3636
EMBED_TOKENS_TRAINED_VAR_THRESHOLD,
37+
_looks_like_local_path,
3738
_propose_key_remap,
39+
_resolve_local_dir,
3840
inspect_dflash_checkpoint,
3941
load_dflash_drafter,
4042
)
@@ -368,3 +370,89 @@ def test_cli_inspect_writes_json(self, tmp_path):
368370
assert "key_remap" in payload
369371
assert "fc.weight" in payload["fc_keys"]
370372
assert "hidden_norm.weight" in payload["hidden_norm_keys"]
373+
374+
375+
# ---------------------------------------------------------------------------
376+
# 5. Local-path heuristic + fail-fast resolver
377+
# (Regression for 2026-06-09 user-side bug: DRAFTER_ID=models/dflash-
378+
# kakeya-baseline silently fell through to HF Hub fetch when the local
379+
# LFS-pulled directory wasn't present, and HF returned 404 with a
380+
# misleading error message far from the root cause.)
381+
# ---------------------------------------------------------------------------
382+
383+
384+
class TestLooksLikeLocalPath:
385+
386+
def test_models_prefix(self):
387+
assert _looks_like_local_path("models/dflash-kakeya-baseline") is True
388+
assert _looks_like_local_path("models/foo") is True
389+
390+
def test_relative_prefixes(self):
391+
assert _looks_like_local_path("./models/foo") is True
392+
assert _looks_like_local_path("../models/foo") is True
393+
394+
def test_absolute_prefix(self):
395+
assert _looks_like_local_path("/Users/me/models/foo") is True
396+
assert _looks_like_local_path("/tmp/checkpoint") is True
397+
398+
def test_hf_repo_id_does_not_match(self):
399+
assert _looks_like_local_path("z-lab/gemma-4-26B-A4B-it-DFlash") is False
400+
assert _looks_like_local_path("google/gemma-3-1b-it") is False
401+
assert _looks_like_local_path("FakeRockert543/gemma-4-26b-a4b-it-MLX-4bit") is False
402+
assert _looks_like_local_path("dllm-hub/Qwen3-0.6B-diffusion-mdlm-v0.1") is False
403+
404+
405+
class TestResolveLocalDirFailFast:
406+
"""Regression for 2026-06-09 user-side bug.
407+
408+
User report: ``DRAFTER_ID=models/dflash-kakeya-baseline`` was treated
409+
as an HF repo id and the script tried to download from HF, which
410+
returned 404. Pre-fix _resolve_local_dir silently fell through to
411+
huggingface_hub.snapshot_download for any non-existent local path.
412+
Post-fix it raises FileNotFoundError with an actionable message.
413+
"""
414+
415+
def test_local_path_that_exists_is_returned(self, tmp_path):
416+
d = _write_tiny_checkpoint(
417+
tmp_path / "models" / "dflash-kakeya-baseline",
418+
use_drafter_prefix=False, include_extras=True,
419+
embed_tokens_trained=True,
420+
)
421+
result = _resolve_local_dir(str(d), {})
422+
assert result == d
423+
424+
def test_local_path_that_does_not_exist_raises(self):
425+
with pytest.raises(FileNotFoundError) as excinfo:
426+
_resolve_local_dir("models/dflash-kakeya-baseline", {})
427+
msg = str(excinfo.value)
428+
assert "does not exist on disk" in msg
429+
assert "git lfs pull" in msg
430+
assert "current working directory" in msg.lower()
431+
432+
def test_relative_path_that_does_not_exist_raises(self):
433+
with pytest.raises(FileNotFoundError):
434+
_resolve_local_dir("./models/missing", {})
435+
with pytest.raises(FileNotFoundError):
436+
_resolve_local_dir("../models/missing", {})
437+
438+
def test_absolute_path_that_does_not_exist_raises(self):
439+
with pytest.raises(FileNotFoundError):
440+
_resolve_local_dir("/tmp/definitely-not-a-real-checkpoint", {})
441+
442+
def test_hf_repo_id_falls_through_to_hf_hub(self, monkeypatch):
443+
"""For a non-local-looking input (HF repo id format), the resolver
444+
should still call huggingface_hub.snapshot_download — the fail-fast
445+
path is local-path-specific."""
446+
called = {}
447+
448+
def fake_snapshot_download(**kwargs):
449+
called["kwargs"] = kwargs
450+
return "/tmp/fake-cached-snapshot"
451+
452+
import huggingface_hub
453+
monkeypatch.setattr(
454+
huggingface_hub, "snapshot_download", fake_snapshot_download,
455+
)
456+
result = _resolve_local_dir("z-lab/gemma-4-26B-A4B-it-DFlash", {})
457+
assert called["kwargs"]["repo_id"] == "z-lab/gemma-4-26B-A4B-it-DFlash"
458+
assert str(result) == "/tmp/fake-cached-snapshot"

0 commit comments

Comments
 (0)