{"record":{"id":"38d038b073cdf452","repo":"RyanCodrai/turbovec","slug":"prefix-version-this-turbovec-accepts-versions","errorCode":null,"errorMessage":"{prefix} {version}; this turbovec accepts versions {list(compat)}","messagePattern":"(.+?) (.+?); this turbovec accepts versions (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"turbovec-python/python/turbovec/_persist.py","lineNumber":197,"sourceCode":"    The obvious spelling, ``version not in compat``, accepts more than it\n    looks like it does: Python's ``==`` crosses numeric types, so ``2.0``\n    and ``True`` compare equal to ``2`` and ``1`` (#350). A side-car\n    written by a JavaScript producer naturally carries ``2.0`` — JSON has\n    one number type and ``JSON.stringify(2.0)`` is only ``\"2\"`` by luck of\n    the value being integral. A version field is an identifier, not a\n    quantity, so the type has to match too: this requires an ``int``, and\n    ``bool`` is excluded even though it is a subclass of ``int``.\n\n    Args:\n        version: the raw value read from the side-car.\n        compat: the schema versions this build accepts.\n        prefix: message lead-in, e.g. ``\"docstore.json has schema version\"``.\n\n    Raises:\n        ValueError: if ``version`` is not an ``int``, or is not in ``compat``.\n    \"\"\"\n    if type(version) is not int or version not in compat:\n        raise ValueError(\n            f\"{prefix} {version}; this turbovec accepts versions {list(compat)}\"\n        )\n\n\ndef _crumb_path(entry) -> str:\n    \"\"\"Rebuild ``payload['docs']['a']['metadata'][1]`` from a stack entry.\n\n    Only called on the failure path — see ``_check_json_faithful`` for why\n    the walk carries parent links instead of prebuilt path strings.\n    \"\"\"\n    keys = []\n    while entry is not None:\n        _obj, parent, key = entry\n        if parent is not None:\n            keys.append(f\"[{key!r}]\" if isinstance(key, str) else f\"[{key}]\")\n        entry = parent\n    return \"payload\" + \"\".join(reversed(keys))\n","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/RyanCodrai/turbovec/blob/ccab9f325e6ce2a270a87daf01ae4e443bcf2d49/turbovec-python/python/turbovec/_persist.py#L179-L215","documentation":"check_schema_version validates the schema-version field read from a persisted store before loading it. It requires the value to be exactly an int (bools and floats rejected via `type(version) is not int`) and to be one of the accepted versions; otherwise it raises ValueError naming the found version and the accepted set.","triggerScenarios":"Calling `load`, `load_from_disk`, `from_persist_path`, or `_load_from` on a file whose schema-version is missing, a float/bool/string, a bool (True == 1 passes `in` but not the type check), or written by a newer/older turbovec with a different version; calling check_schema_version directly in tests or validators.","commonSituations":"Opening a .tvim/JSON pair written by a different turbovec release after an upgrade; hand-edited side-car where the version became a string like \"2\"; a serializer that wrote 2.0 instead of 2.","solutions":["Check the file's recorded schema version and compare against the versions your turbovec accepts (listed in the error message).","Re-save the store with the turbovec version that wrote it, then migrate, or upgrade/downgrade turbovec to a version accepting that schema.","Fix a hand-edited side-car so the version is a JSON integer (2, not \"2\" or 2.0).","Wrap in try/except ValueError and surface a clear 'incompatible store version' message to the user instead of a raw traceback."],"exampleFix":"// before\nversion = json.load(f)['schema_version']  # \"2\" (string)\n// after\nversion = int(json.load(f)['schema_version'])\ncheck_schema_version(version, {1, 2}, prefix=\"docstore.json has schema version\")","handlingStrategy":"try-catch","validationCode":"def schema_ok(version, compat={1, 2}):\n    return type(version) is int and version in compat","typeGuard":"def is_schema_version(v) -> bool:\n    return type(v) is int","tryCatchPattern":"try:\n    store = turbovec.load(path)\nexcept ValueError as e:\n    if 'accepts versions' in str(e):\n        print('store schema incompatible:', e)\n    else:\n        raise","preventionTips":["Check the schema version in the side-car against your library version before loading.","Never hand-edit the schema-version field; keep it a JSON integer.","Re-export/migrate stores when upgrading turbovec instead of loading old files directly.","Remember bool is not accepted: type(v) is int, not isinstance(v, int)."],"tags":["python","validation","schema","versioning","persistence"],"backgroundTag":"schema-validation-failed","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"}