RyanCodrai/turbovec · error · ValueError

; this turbovec accepts versions

Error message

{prefix} {version}; this turbovec accepts versions {list(compat)}

What it means

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.

Solutions

  1. Check the file's recorded schema version and compare against the versions your turbovec accepts (listed in the error message).
  2. Re-save the store with the turbovec version that wrote it, then migrate, or upgrade/downgrade turbovec to a version accepting that schema.
  3. Fix a hand-edited side-car so the version is a JSON integer (2, not "2" or 2.0).
  4. Wrap in try/except ValueError and surface a clear 'incompatible store version' message to the user instead of a raw traceback.

Example fix

// before
version = json.load(f)['schema_version']  # "2" (string)
// after
version = int(json.load(f)['schema_version'])
check_schema_version(version, {1, 2}, prefix="docstore.json has schema version")
Defensive patterns

Strategy: try-catch

Validate before calling

def schema_ok(version, compat={1, 2}):
    return type(version) is int and version in compat

Type guard

def is_schema_version(v) -> bool:
    return type(v) is int

Try / catch

try:
    store = turbovec.load(path)
except ValueError as e:
    if 'accepts versions' in str(e):
        print('store schema incompatible:', e)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of RyanCodrai/turbovec@ccab9f325e (2026-09-06). Data as JSON: /api/errors/38d038b073cdf452. Report an issue: GitHub.

Appendix: source

Thrown at turbovec-python/python/turbovec/_persist.py:197

    The obvious spelling, ``version not in compat``, accepts more than it
    looks like it does: Python's ``==`` crosses numeric types, so ``2.0``
    and ``True`` compare equal to ``2`` and ``1`` (#350). A side-car
    written by a JavaScript producer naturally carries ``2.0`` — JSON has
    one number type and ``JSON.stringify(2.0)`` is only ``"2"`` by luck of
    the value being integral. A version field is an identifier, not a
    quantity, so the type has to match too: this requires an ``int``, and
    ``bool`` is excluded even though it is a subclass of ``int``.

    Args:
        version: the raw value read from the side-car.
        compat: the schema versions this build accepts.
        prefix: message lead-in, e.g. ``"docstore.json has schema version"``.

    Raises:
        ValueError: if ``version`` is not an ``int``, or is not in ``compat``.
    """
    if type(version) is not int or version not in compat:
        raise ValueError(
            f"{prefix} {version}; this turbovec accepts versions {list(compat)}"
        )


def _crumb_path(entry) -> str:
    """Rebuild ``payload['docs']['a']['metadata'][1]`` from a stack entry.

    Only called on the failure path — see ``_check_json_faithful`` for why
    the walk carries parent links instead of prebuilt path strings.
    """
    keys = []
    while entry is not None:
        _obj, parent, key = entry
        if parent is not None:
            keys.append(f"[{key!r}]" if isinstance(key, str) else f"[{key}]")
        entry = parent
    return "payload" + "".join(reversed(keys))

View on GitHub (pinned to ccab9f325e)