{"record":{"id":"4da1bb07d3b7fc93","repo":"cocoindex-io/cocoindex","slug":"change-fingerprint-fp-is-present-in-a-cached-mem","errorCode":null,"errorMessage":"change fingerprint {fp} is present in a cached memo entry but has no registered state functions in the current ContextProvider — this should be unreachable under the shook-tag canonicalization invariant.","messagePattern":"change fingerprint (.+?) is present in a cached memo entry but has no registered state functions in the current ContextProvider — this should be unreachable under the shook-tag canonicalization invariant\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/function.py","lineNumber":417,"sourceCode":"    Used on cache-hit validation: for each stored ``fp → states`` entry we\n    look up the matching state functions in the env registry.\n\n    Under the shook-tag invariant this lookup always succeeds: if the user\n    had removed ``__coco_memo_state__`` from the value's type between runs,\n    the canonicalization would produce a different fingerprint (``hook`` vs\n    ``shook`` tag) and the entry would already have been invalidated by\n    `all_contained_with_env` before we reach this point. If a stored fp has\n    no registered state fns we raise — that indicates registry/state drift\n    or a bug in the shook-tag machinery.\n    \"\"\"\n    if not stored:\n        return []\n    provider = env.context_provider\n    entries: list[tuple[core.Fingerprint, list[StateFnEntry]]] = []\n    for fp in stored:\n        state_fns = provider.get_context_state_fns(fp)\n        if state_fns is None:\n            raise RuntimeError(\n                f\"change fingerprint {fp} is present in a cached memo \"\n                \"entry but has no registered state functions in the current \"\n                \"ContextProvider — this should be unreachable under the \"\n                \"shook-tag canonicalization invariant.\"\n            )\n        entries.append((fp, state_fns))\n    return entries\n\n\ndef _has_self_parameter(fn: Callable[..., Any]) -> bool:\n    \"\"\"Check if function has 'self' as first parameter (i.e., is a method).\"\"\"\n    sig = inspect.signature(fn)\n    params = list(sig.parameters.values())\n    if not params:\n        return False\n    first = params[0]\n    return first.name == \"self\" and first.kind in (\n        inspect.Parameter.POSITIONAL_ONLY,","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/function.py#L399-L435","documentation":"When replaying a cached memo entry, each stored change fingerprint must have state functions registered in the current ContextProvider. If a fingerprint is stored but unregistered, the shook-tag canonicalization invariant is broken — this is an internal consistency check and indicates a bug or stale/corrupted cache shared across environments.","triggerScenarios":"Calling a memoized @coco.fn whose cached entry (from a previous run/environment) references fingerprints the current Environment's ContextProvider doesn't know — e.g. cache persisted across process restarts with a differently-populated provider, or functions registered in one environment but replayed in another.","commonSituations":"Sharing memo/LMDB storage between environments or processes; reordering context provider registrations; upgrading code where state functions were renamed/removed while old cache entries remain.","solutions":["Clear the memo cache / stored state for the affected function and re-run","Ensure the same functions are registered (same order) in the Environment providing the context state","Verify you're not mixing memo entries across different environments or processes","Report as a bug if reproducible with a single environment — it violates the documented invariant"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"provider = env.context_provider\nmissing = [fp for fp in cached_fingerprints if provider.get_context_state_fns(fp) is None]\nif missing:\n    clear_memo_cache()  # stale cache across environments","typeGuard":null,"tryCatchPattern":"try:\n    result = await memoized_fn(*args)\nexcept RuntimeError as e:\n    if \"shook-tag canonicalization\" in str(e):\n        clear_memo_cache()\n        result = await memoized_fn(*args)","preventionTips":["Don't share memo cache storage across different environments or processes","Register context state functions deterministically (same order) per environment","Invalidate caches after upgrading/renaming state functions"],"tags":["memoization","internal-invariant","cache"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}