666ghj/MiroFish · critical · StarHistoryError

unsupported history schema_version

Error message

unsupported history schema_version

What it means

validate_state requires schema_version to be exactly int 1 (note the order: != 1 is checked before the type check, so 1.0/True/'1' also fail since True != 1 is False but type(True) is not int — both clauses combine to reject anything that is not a literal int 1). Anything else raises StarHistoryError('unsupported history schema_version'). This is the version gate for the state file format.

Source

Thrown at scripts/star_history.py:360


def validate_state(state: Any) -> None:
    if not isinstance(state, dict):
        raise StarHistoryError("history state must be a JSON object")
    _expect_keys(
        state,
        {
            "schema_version",
            "repository",
            "timezone",
            "ongoing_interval_days",
            "reconstruction",
            "snapshots",
        },
        "history state",
    )
    if state["schema_version"] != 1 or type(state["schema_version"]) is not int:
        raise StarHistoryError("unsupported history schema_version")
    if state["repository"] != REPOSITORY:
        raise StarHistoryError("history repository does not match configured repository")
    if state["timezone"] != "UTC":
        raise StarHistoryError("history timezone must be UTC")
    if (
        state["ongoing_interval_days"] != INTERVAL_DAYS
        or type(state["ongoing_interval_days"]) is not int
    ):
        raise StarHistoryError(
            f"history interval must be exactly {INTERVAL_DAYS} days"
        )

    reconstruction = state["reconstruction"]
    if not isinstance(reconstruction, dict):
        raise StarHistoryError("reconstruction must be an object")
    _expect_keys(
        reconstruction,
        {"method", "generated_at", "daily"},

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Update the script to the version that wrote the state file (or downgrade the state by regenerating it)
  2. Discard the state file and let the script perform a full reconstruction
  3. Never hand-edit schema_version — the surrounding structure must match the version

Example fix

// before (state file)
"schema_version": 2

// after (state file — only if the rest of the file genuinely matches v1)
"schema_version": 1
Defensive patterns

Strategy: validation

Validate before calling

version = state.get("schema_version")
if type(version) is not int or version != 1:
    raise StarHistoryError(f"state schema_version {version!r} unsupported; this script supports exactly 1")

Type guard

def is_supported_state_version(value: object) -> TypeGuard[int]:
    return type(value) is int and value == 1

Try / catch

try:
    validate_state(state)
except StarHistoryError as exc:
    if "unsupported history schema_version" in str(exc):
        regenerate_state_file()  # state from another version; rebuild
    else:
        raise

Prevention

When it happens

Trigger: State file with schema_version: 2 (written by a newer script), "1" (string), 1.0 (float), or true (bool); also missing-schema_version variants are caught earlier by _expect_keys.

Common situations: Running an older script version against a state file produced by a newer version; hand-edited version field; a fork that bumped the schema.

Related errors


AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14). Data as JSON: /api/errors/833106bfe5075dc4. Report an issue: GitHub.