Skip to content

Read stale pickled tagging-cache entries as misses, not 500s - #974

Merged
ajslater merged 3 commits into
developfrom
fix-tagging-cache-stale-pickle
Oct 8, 2026
Merged

ajslater merged 3 commits into
developfrom
fix-tagging-cache-stale-pickle

Conversation

@ajslater

@ajslater ajslater commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Problem

After upgrading to the 2.5.4 image, a user with online-tag matches pending review sees ModuleNotFoundError: No module named 'numpy' at startup (logged under "Clearing stale online tag scan marker on startup") and as 500s on /api/v4/admin/tag-prompts and /api/v4/admin/tag-sessions/snapshot.

Codex 2.5.3 (comicbox 5.2.2) scored covers with imagehash, whose hash distance is numpy.int64, so cover_score and the blended score were numpy.float64. serialize_candidate copied them into each pending prompt, which is pickled into the file-based tagging cache and kept across restarts. 2.5.4 (comicbox 5.3.1, which uses a pure-Python pHash) no longer installs numpy, so every read of those prompts fails while unpickling. ResilientFileBasedCache only treated zlib.error, UnpicklingError and EOFError as unreadable, so the error reached the caller.

Changes

  • ResilientFileBasedCache also treats ImportError and AttributeError raised while loading an entry as unreadable: delete the file, report a miss. A pickle naming a module or class that no longer exists is as unloadable as a truncated one.
  • The discard is logged as a warning (previously debug) with the cache key and the traceback. The file is gone afterwards, so the log is the only record, both for an admin whose review queue emptied and for debugging if this ever catches something it shouldn't.
  • serialize_candidate casts score, metadata_score and cover_score to plain float, so a library's number type can't end up in the cache again.
  • NEWS: new v2.5.5 section.

Prompts already stored with numpy scores are dropped on first read; those comics need another online-tag pass.

Testing

  • New tests/test_resilient_cache.py saves a value whose class comes from a temporary module, then removes the module (ModuleNotFoundError) or just the class (AttributeError). It covers get, touch, the warning's content and the startup prompt prune. All of them failed before the fix with the same ModuleNotFoundError from Django's filebased.py that the user reported.
  • New plain-float test in tests/test_onlinetag_serialize_candidate.py.
  • make fix, make lint, make ty clean; make test: 1668 passed, 1 xfailed (Python), 994 passed (frontend).
  • make lint still shows two existing reportUnreachable warnings in codex/views/browser/annotate/cover.py:63,69; this PR doesn't touch that file.

🤖 Generated with Claude Code

ajslater and others added 3 commits October 7, 2026 21:33
Codex 2.5.3 (comicbox 5.2.2) pickled imagehash's numpy.float64 cover
scores into pending online-tag prompts. 2.5.4 (comicbox 5.3.1) ships
without numpy, so every read of those prompts raised
ModuleNotFoundError: the daemon's startup prune (logged under "Clearing
stale online tag scan marker on startup"), /admin/tag-prompts and
/admin/tag-sessions/snapshot.

- ResilientFileBasedCache also treats ImportError and AttributeError on
  load as an unreadable entry: delete the file, report a miss. A pickle
  naming a module or class that no longer exists is as unloadable as a
  truncated one. The discard now logs a warning, so an admin whose
  review queue emptied after an upgrade can see why.
- serialize_candidate casts score, metadata_score and cover_score to
  plain float, so a library's number type can't end up in the cache
  again.

Prompts already stored with numpy scores are dropped; those comics need
another online-tag pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The discard deletes the file, so the log line is the only record of
what was dropped and why. Name the cache key (the file name is a hash)
and attach the traceback, so an error class caught there by mistake
can be traced from the log alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ajslater
ajslater merged commit f9d0382 into develop Oct 8, 2026
9 checks passed
@ajslater
ajslater deleted the fix-tagging-cache-stale-pickle branch October 8, 2026 05:40
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.

1 participant