{"record":{"id":"c29632db22057786","repo":"RyanCodrai/turbovec","slug":"persisted-store-is-corrupt-len-extraneous-wha","errorCode":null,"errorMessage":"persisted store is corrupt: {len(extraneous)} {what} id(s) present in `{sidecar_name}` but missing from `{mapping_name}` (e.g. {sample}). The JSON side-car's maps are out of sync.","messagePattern":"persisted store is corrupt: (.+?) (.+?) id\\(s\\) present in `(.+?)` but missing from `(.+?)` \\(e\\.g\\. (.+?)\\)\\. The JSON side-car's maps are out of sync\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"turbovec-python/python/turbovec/_persist.py","lineNumber":517,"sourceCode":"    mapping_set = set(mapping_keys)\n    sidecar_set = set(sidecar_keys)\n    if mapping_set == sidecar_set:\n        return\n    missing = mapping_set - sidecar_set\n    if missing:\n        # key=repr: a hand-corrupted side-car can hold mixed-type ids\n        # (JSON arrays survive parsing with e.g. an int among strings),\n        # which plain sorted() would turn into a TypeError instead of\n        # the promised ValueError.\n        sample = \", \".join(repr(k) for k in sorted(missing, key=repr)[:3])\n        raise ValueError(\n            f\"persisted store is corrupt: {len(missing)} {what} id(s) present \"\n            f\"in `{mapping_name}` but missing from `{sidecar_name}` \"\n            f\"(e.g. {sample}). The JSON side-car's maps are out of sync.\"\n        )\n    extraneous = sidecar_set - mapping_set\n    sample = \", \".join(repr(k) for k in sorted(extraneous, key=repr)[:3])\n    raise ValueError(\n        f\"persisted store is corrupt: {len(extraneous)} {what} id(s) present \"\n        f\"in `{sidecar_name}` but missing from `{mapping_name}` \"\n        f\"(e.g. {sample}). The JSON side-car's maps are out of sync.\"\n    )\n\n\n__all__ = [\"check_persisted_handles\", \"check_schema_version\", \"check_sidecar_keysets\"]\n","sourceCodeStart":499,"sourceCodeEnd":525,"githubUrl":"https://github.com/RyanCodrai/turbovec/blob/ccab9f325e6ce2a270a87daf01ae4e443bcf2d49/turbovec-python/python/turbovec/_persist.py#L499-L525","documentation":"check_sidecar_keysets validates that the JSON side-car's id maps cover exactly the same keys as the main persisted mapping. If the side-car contains ids absent from the mapping (extraneous set), the persisted store is considered corrupt and a ValueError is raised with a sample of up to 3 offending ids. This guards against silent data loss or inconsistency when loading a persisted store.","triggerScenarios":"Calling load() or from_persist_path() on a persisted store whose sidecar_name map contains id(s) not present in the mapping_name map; also raised directly by tests that simulate mixed-type ids in the sidecar keyset.","commonSituations":"Manual editing of the persisted JSON side-car, a partial/interrupted save that wrote the side-car but not the main mapping, an older or newer library version changing the mapping format, or copying/syncing files independently so the two files diverge.","solutions":["Rebuild the persisted store from source data: re-save the index and side-car atomically with the library's save/persist API instead of loading the corrupt pair.","Remove the extraneous ids from the side-car JSON (or add the corresponding entries to the mapping) so both keysets match exactly.","Restore both the main file and side-car from a consistent backup taken at the same time.","Check for version mismatches between the library version that wrote the store and the one loading it; re-persist with the current version."],"exampleFix":"# before (corrupt side-car with extra id)\nsidecar_ids = {1, 2, \"3\"}; mapping_ids = {1, 2}  # ValueError\n# after\n# re-persist both files together:\nstore.save_to_persist_path(path)  # writes mapping + side-car atomically","handlingStrategy":"validation","validationCode":"import json\nsidecar_ids = set(json.load(open(sidecar_path))['ids'])\nmapping_ids = set(store.mapping.keys())\nif sidecar_ids != mapping_ids:\n    raise ValueError(f\"persisted store corrupt: {sidecar_ids ^ mapping_ids}\")","typeGuard":null,"tryCatchPattern":"try:\n    store = TurboStore.from_persist_path(path)\nexcept ValueError as e:\n    logger.error(\"corrupt persisted store: %s\", e)\n    store = rebuild_store_from_source()","preventionTips":["Always save the mapping and side-car atomically (temp file + rename) as one unit.","Never hand-edit the persisted JSON files.","Take backups of both files together and restore them together."],"tags":["persistence","data-corruption","validation"],"backgroundTag":"checksum-mismatch","analyzedSha":"ccab9f325e6ce2a270a87daf01ae4e443bcf2d49","analyzedAt":"2026-09-06T08:39:18.516Z","contentChangedAt":"2026-09-06T08:39:18.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}