goumsss Claude Opus 4.8 commited on
Commit
a108fbc
·
1 Parent(s): fb5e5c4

Fix poisoned HF cache: fresh path + self-healing wipe

Browse files

The /data/hf_cache tree was poisoned by partial downloads — xet and
huggingface_hub left files where directories belong, causing
[Errno 20] Not a directory on every generation attempt.

- Bump cache path to /data/hf_cache_v3 to escape the poisoned tree
- Set HF_HOME + HF_HUB_CACHE explicitly (no per-call cache_dir)
- Validate cache by checking for model_index.json in a snapshot
- If invalid, shutil.rmtree the whole subtree before re-downloading so
every attempt starts from clean ground (xet/.locks/blobs can create
real dirs)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files changed (1) hide show
  1. image_generator.py +34 -22
image_generator.py CHANGED
@@ -35,29 +35,42 @@ if IS_HF_SPACE:
35
  # ---------------------------------------------------------------------------
36
  # Persistent storage cache — survives sleep/restart on HF Spaces
37
  # ---------------------------------------------------------------------------
38
- if IS_HF_SPACE and os.path.isdir("/data"):
39
- _cache_dir = "/data/hf_cache"
40
- os.makedirs(_cache_dir, exist_ok=True)
41
- os.environ.setdefault("HF_HOME", _cache_dir)
42
- print(f"Persistent cache active → {_cache_dir}")
 
43
 
44
- # Clean up stale placeholder files left by previous failed downloads.
45
- # huggingface_hub creates files where it expects directories — remove them.
46
  import shutil
47
- _model_cache = os.path.join(_cache_dir, "models--black-forest-labs--FLUX.2-klein-4B")
48
- _locks_path = os.path.join(_cache_dir, ".locks", "models--black-forest-labs--FLUX.2-klein-4B")
49
- for _stale in [_model_cache, _locks_path]:
50
- try:
51
- if os.path.isfile(_stale):
52
- os.remove(_stale)
53
- print(f"Removed stale placeholder file: {_stale}")
54
- except Exception as _e:
55
- print(f"⚠️ Could not remove {_stale}: {_e}")
56
-
57
- if os.path.isdir(_model_cache):
58
- print(f"✅ FLUX.2-klein-4B already cached — skipping download")
 
 
 
 
59
  else:
60
- print(f"Downloading FLUX.2-klein-4B to persistent cache…")
 
 
 
 
 
 
 
 
 
61
  try:
62
  from huggingface_hub import snapshot_download
63
  _hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
@@ -67,8 +80,7 @@ if IS_HF_SPACE and os.path.isdir("/data"):
67
  asyncio.set_event_loop(loop)
68
  try:
69
  snapshot_download(
70
- "black-forest-labs/FLUX.2-klein-4B",
71
- cache_dir=_cache_dir,
72
  token=_hf_token,
73
  ignore_patterns=["*.msgpack", "*.h5", "flax_model*"],
74
  )
 
35
  # ---------------------------------------------------------------------------
36
  # Persistent storage cache — survives sleep/restart on HF Spaces
37
  # ---------------------------------------------------------------------------
38
+ # NOTE: a partially-written cache poisons the tree — huggingface_hub/xet leave
39
+ # files where directories are expected ([Errno 20] Not a directory). We use a
40
+ # fresh cache path and self-heal: if the model isn't *validly* cached, wipe the
41
+ # whole subtree so every download attempt starts from clean ground.
42
+ _MODEL_ID = "black-forest-labs/FLUX.2-klein-4B"
43
+ _MODEL_DIR = "models--black-forest-labs--FLUX.2-klein-4B"
44
 
45
+ if IS_HF_SPACE and os.path.isdir("/data"):
 
46
  import shutil
47
+ _cache_dir = "/data/hf_cache_v3" # bump path to escape any poisoned older cache
48
+ os.environ["HF_HOME"] = _cache_dir
49
+ os.environ["HF_HUB_CACHE"] = os.path.join(_cache_dir, "hub")
50
+
51
+ # A model is "validly cached" only if its snapshot has model_index.json.
52
+ def _is_valid_cache():
53
+ hub = os.path.join(_cache_dir, "hub", _MODEL_DIR, "snapshots")
54
+ if not os.path.isdir(hub):
55
+ return False
56
+ for snap in os.listdir(hub):
57
+ if os.path.isfile(os.path.join(hub, snap, "model_index.json")):
58
+ return True
59
+ return False
60
+
61
+ if _is_valid_cache():
62
+ print(f"✅ FLUX.2-klein-4B already cached at {_cache_dir} — skipping download")
63
  else:
64
+ # Wipe any partial/poisoned state, then recreate clean.
65
+ if os.path.exists(_cache_dir):
66
+ print(f"Cache incomplete — wiping {_cache_dir} for a clean download")
67
+ try:
68
+ shutil.rmtree(_cache_dir)
69
+ except Exception as _e:
70
+ print(f"⚠️ Could not wipe cache: {_e}")
71
+ os.makedirs(os.path.join(_cache_dir, "hub"), exist_ok=True)
72
+
73
+ print(f"Downloading FLUX.2-klein-4B to {_cache_dir}…")
74
  try:
75
  from huggingface_hub import snapshot_download
76
  _hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
 
80
  asyncio.set_event_loop(loop)
81
  try:
82
  snapshot_download(
83
+ _MODEL_ID,
 
84
  token=_hf_token,
85
  ignore_patterns=["*.msgpack", "*.h5", "flax_model*"],
86
  )