github/spec-kit · error · BundlerError

Corrupt records file: {path} — missing 'schema_version'. Exp

Error message

Corrupt records file: {path} — missing 'schema_version'. Expected version {RECORDS_SCHEMA_VERSION}.

What it means

Raised by _check_schema_version when the installed-bundles records file (a JSON file under .specify) lacks 'schema_version' and the caller marked it required (load_records does). The version gate exists so a future incompatible format fails fast with an actionable error instead of being silently mis-parsed, which could cause incorrect bundle attribution or removal.

Source

Thrown at src/specify_cli/bundler/models/records.py:104

            ),
        )


def records_path(project_root: Path) -> Path:
    return Path(project_root) / ".specify" / RECORDS_FILENAME


def _check_schema_version(value: Any, *, path: Path, required: bool) -> None:
    """Reject a records file whose schema version we cannot safely parse.

    A future incompatible format (or a corrupted file) must fail fast with an
    actionable error rather than being silently mis-parsed, which could lead to
    incorrect bundle attribution or removal. Forward-compatible minor bumps that
    keep the same major version are accepted.
    """
    if value is None:
        if required:
            raise BundlerError(
                f"Corrupt records file: {path} — missing 'schema_version'. "
                f"Expected version {RECORDS_SCHEMA_VERSION}."
            )
        return
    seen = str(value).strip()
    if seen.split(".")[0] != RECORDS_SCHEMA_VERSION.split(".")[0]:
        raise BundlerError(
            f"Unsupported records schema version '{seen}' at {path}; this "
            f"Spec Kit understands version {RECORDS_SCHEMA_VERSION}. The file may "
            "have been written by a newer version or is corrupt."
        )


def load_records(project_root: Path) -> list[InstalledBundleRecord]:
    # Defense in depth (mirrors the write path's within= confinement): refuse to
    # read through a symlinked or traversal-escaping ``.specify`` that resolves
    # outside project_root.
    path = ensure_within(project_root, records_path(project_root))

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Add "schema_version": "<RECORDS_SCHEMA_VERSION>" (the major your CLI supports, e.g. "1") to the top level of the records file.
  2. If record contents may be stale, delete the file and reinstall bundles to regenerate it.
  3. Upgrade Spec Kit if a newer version understands the file's origin format.

Example fix

// before
{"bundles": [...]}

// after
{"schema_version": "1", "bundles": [...]}
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

SUPPORTED_RECORDS_MAJOR = "1"  # keep in sync with RECORDS_SCHEMA_VERSION

def records_has_schema_version(path: Path) -> bool:
    data = json.loads(path.read_text())
    return data.get("schema_version") is not None

Try / catch

try:
    records = load_records(project_root)
except BundlerError as e:
    if "missing 'schema_version'" in str(e):
        # add the supported schema_version, or rebuild the file via reinstall
        ...

Prevention

When it happens

Trigger: load_records(project_root) reads an existing records file whose top-level object has no 'schema_version' key; required=True makes the None branch raise. (Other callers may pass required=False for lenient contexts.)

Common situations: Records written by an early/prototype writer that omitted schema_version; hand-created files; files from a downgraded tool version predating the version gate.

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/b9e94ba4130e680d. Report an issue: GitHub.