{"record":{"id":"60c2fcdc386ba015","repo":"666ghj/MiroFish","slug":"label-contains-missing-or-unknown-fields","errorCode":null,"errorMessage":"{label} contains missing or unknown fields","messagePattern":"(.+?) contains missing or unknown fields","errorType":"exception","errorClass":"StarHistoryError","httpStatus":null,"severity":"error","filePath":"scripts/star_history.py","lineNumber":341,"sourceCode":"        raise StarHistoryError(f\"{label} is not a valid UTC timestamp\") from exc\n    return parsed\n\n\ndef _format_state_timestamp(value: datetime) -> str:\n    normalized = _normalize_now(value)\n    return normalized.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n\n\ndef _normalize_now(value: datetime) -> datetime:\n    if value.tzinfo is None or value.utcoffset() != timedelta(0):\n        raise StarHistoryError(\"clock must return a UTC datetime\")\n    return value.astimezone(UTC).replace(microsecond=0)\n\n\ndef _expect_keys(value: Mapping[str, Any], expected: set[str], label: str) -> None:\n    actual = set(value)\n    if actual != expected:\n        raise StarHistoryError(f\"{label} contains missing or unknown fields\")\n\n\ndef validate_state(state: Any) -> None:\n    if not isinstance(state, dict):\n        raise StarHistoryError(\"history state must be a JSON object\")\n    _expect_keys(\n        state,\n        {\n            \"schema_version\",\n            \"repository\",\n            \"timezone\",\n            \"ongoing_interval_days\",\n            \"reconstruction\",\n            \"snapshots\",\n        },\n        \"history state\",\n    )\n    if state[\"schema_version\"] != 1 or type(state[\"schema_version\"]) is not int:","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/scripts/star_history.py#L323-L359","documentation":"_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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run the script's state migration/reset path instead of hand-editing the JSON","Diff the state file's actual keys against the exact expected set named in the error label, then add missing / remove unknown keys","If the file came from a newer script version, downgrade mismatch or regenerate the state from scratch"],"exampleFix":"// before (state file, extra key)\n{ \"schema_version\": 1, ..., \"snapshots\": [], \"notes\": \"edited\" }\n\n// after (state file)\n{ \"schema_version\": 1, \"repository\": \"...\", \"timezone\": \"UTC\", \"ongoing_interval_days\": 13, \"reconstruction\": {...}, \"snapshots\": [] }","handlingStrategy":"validation","validationCode":"EXPECTED_ROOT = {\"schema_version\", \"repository\", \"timezone\", \"ongoing_interval_days\", \"reconstruction\", \"snapshots\"}\nmissing = EXPECTED_ROOT - set(state)\nunknown = set(state) - EXPECTED_ROOT\nif missing or unknown:\n    raise StarHistoryError(f\"state keys wrong: missing={missing} unknown={unknown}\")","typeGuard":"def has_exact_keys(value: object, expected: set[str]) -> TypeGuard[dict]:\n    return isinstance(value, dict) and set(value) == expected","tryCatchPattern":"try:\n    validate_state(state)\nexcept StarHistoryError as exc:\n    if \"missing or unknown fields\" in str(exc):\n        raise StarHistoryError(\"state file schema drifted — regenerate it with the current script version\") from exc\n    raise","preventionTips":["Regenerate state files after upgrading the script instead of reusing old ones","Treat the state schema as closed: never add keys to the JSON by hand"],"tags":["state-file","schema","validation","star-history"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}