666ghj/MiroFish · error · StarHistoryError

reconstruction must be an object

Error message

reconstruction must be an object

What it means

Raised by validate_state() in scripts/star_history.py when the 'reconstruction' field of the star-history JSON state file is not a JSON object (dict). The validator requires the whole state document to match an exact schema, and reconstruction must be a dict with exactly the keys 'method', 'generated_at', and 'daily'. This error means the shape is fundamentally wrong before any field-level checks run.

Source

Thrown at scripts/star_history.py:375

        "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"},
        "reconstruction",
    )
    reconstruction_method = reconstruction["method"]
    if reconstruction_method not in {
        "current_stargazers_starred_at",
        "aggregate_snapshot_only",
    }:
        raise StarHistoryError("unsupported reconstruction method")
    generated_at = _parse_state_timestamp(
        reconstruction["generated_at"], "reconstruction.generated_at"
    )
    daily = reconstruction["daily"]
    if not isinstance(daily, list):
        raise StarHistoryError("reconstruction.daily must be a list")
    if reconstruction_method == "aggregate_snapshot_only" and daily:

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Restore 'reconstruction' to a JSON object: {"method": ..., "generated_at": ..., "daily": [...]}
  2. If the file was hand-edited, re-run the generation step instead of editing state manually
  3. Check schema_version is 1 and the file matches the current script version's expected layout

Example fix

// before
"reconstruction": [{"date": "2024-01-01", "stars": 10}]
// after
"reconstruction": {
  "method": "current_stargazers_starred_at",
  "generated_at": "2024-01-02T00:00:00Z",
  "daily": [{"date": "2024-01-01", "stars": 10}]
}
Defensive patterns

Strategy: validation

Validate before calling

import json
state = json.loads(state_text)
rec = state.get("reconstruction")
assert isinstance(rec, dict), "reconstruction must be an object"

Type guard

def is_reconstruction_object(value) -> bool:
    return isinstance(value, dict)

Try / catch

try:
    validate_state(state)
except StarHistoryError as exc:
    if "reconstruction must be an object" in str(exc):
        # regenerate or reject the state file
        ...

Prevention

When it happens

Trigger: Calling validate_state(state) or canonical_state_bytes(state) (which calls validate_state internally) on a state dict where state['reconstruction'] is a list, string, number, null, or is missing-adjacent (e.g. hand-edited state file where reconstruction was replaced by an array of points).

Common situations: Hand-editing the state JSON and replacing the reconstruction object with a bare array of {date, stars} points; consuming a state file produced by a different/older version of the script with a different schema; deserializing YAML/JSON where the nesting level was flattened by mistake.

Related errors


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