666ghj/MiroFish · error · StarHistoryError

{label} contains missing or unknown fields

Error message

{label} contains missing or unknown fields

What it means

_expect_keys compares set(value) against an exact expected key set for a state (sub)object — for the root: schema_version, repository, timezone, ongoing_interval_days, reconstruction, snapshots; for reconstruction: method, generated_at, daily. Any missing or extra key raises StarHistoryError(f'{label} contains missing or unknown fields'). The schema is intentionally closed: unknown fields signal a version mismatch rather than being ignored.

Source

Thrown at scripts/star_history.py:341

        raise StarHistoryError(f"{label} is not a valid UTC timestamp") from exc
    return parsed


def _format_state_timestamp(value: datetime) -> str:
    normalized = _normalize_now(value)
    return normalized.strftime("%Y-%m-%dT%H:%M:%SZ")


def _normalize_now(value: datetime) -> datetime:
    if value.tzinfo is None or value.utcoffset() != timedelta(0):
        raise StarHistoryError("clock must return a UTC datetime")
    return value.astimezone(UTC).replace(microsecond=0)


def _expect_keys(value: Mapping[str, Any], expected: set[str], label: str) -> None:
    actual = set(value)
    if actual != expected:
        raise StarHistoryError(f"{label} contains missing or unknown fields")


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:

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Run the script's state migration/reset path instead of hand-editing the JSON
  2. Diff the state file's actual keys against the exact expected set named in the error label, then add missing / remove unknown keys
  3. If the file came from a newer script version, downgrade mismatch or regenerate the state from scratch

Example fix

// before (state file, extra key)
{ "schema_version": 1, ..., "snapshots": [], "notes": "edited" }

// after (state file)
{ "schema_version": 1, "repository": "...", "timezone": "UTC", "ongoing_interval_days": 13, "reconstruction": {...}, "snapshots": [] }
Defensive patterns

Strategy: validation

Validate before calling

EXPECTED_ROOT = {"schema_version", "repository", "timezone", "ongoing_interval_days", "reconstruction", "snapshots"}
missing = EXPECTED_ROOT - set(state)
unknown = set(state) - EXPECTED_ROOT
if missing or unknown:
    raise StarHistoryError(f"state keys wrong: missing={missing} unknown={unknown}")

Type guard

def has_exact_keys(value: object, expected: set[str]) -> TypeGuard[dict]:
    return isinstance(value, dict) and set(value) == expected

Try / catch

try:
    validate_state(state)
except StarHistoryError as exc:
    if "missing or unknown fields" in str(exc):
        raise StarHistoryError("state file schema drifted — regenerate it with the current script version") from exc
    raise

Prevention

When it happens

Trigger: A state file missing 'reconstruction' (older schema), carrying an extra field like 'notes' from a future version, or a reconstruction object lacking 'daily'; also produced by third-party tools that add metadata keys.

Common situations: State file written by an older or newer version of the script; hand-editing that added/renamed a key; a CI job merging state files from different script versions.

Related errors


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