666ghj/MiroFish · error · StarHistoryError

reconstruction point must be an object

Error message

reconstruction point must be an object

What it means

Raised by validate_state() while iterating reconstruction.daily when an element is not a JSON object. Each daily point must be a dict with exactly the keys 'date' and 'stars' (enforced next by _expect_keys); arrays, strings, numbers, or nulls fail here.

Source

Thrown at scripts/star_history.py:400

    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:
        raise StarHistoryError("aggregate-only history cannot contain reconstructed dates")

    previous_day: date | None = None
    previous_stars = 0
    for index, raw_point in enumerate(daily):
        if not isinstance(raw_point, dict):
            raise StarHistoryError("reconstruction point must be an object")
        _expect_keys(raw_point, {"date", "stars"}, "reconstruction point")
        raw_date = raw_point["date"]
        if not isinstance(raw_date, str):
            raise StarHistoryError("reconstruction date must be a string")
        try:
            point_day = date.fromisoformat(raw_date)
        except ValueError as exc:
            raise StarHistoryError("reconstruction date is invalid") from exc
        if point_day.isoformat() != raw_date:
            raise StarHistoryError("reconstruction date is not canonical")
        stars = _strict_non_negative_int(raw_point["stars"], "reconstruction stars")
        if index == 0 and stars <= 0:
            raise StarHistoryError("first reconstruction point must have stars")
        if previous_day is not None and point_day <= previous_day:
            raise StarHistoryError("reconstruction dates must be strictly increasing")
        if index > 0 and stars <= previous_stars:
            raise StarHistoryError("reconstruction stars must be strictly increasing")
        if point_day >= generated_at.date():

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Make every daily element an object {"date": ..., "stars": ...} with exactly those two keys
  2. Remove any extra fields — _expect_keys rejects unknown as well as missing fields
  3. Regenerate the state with the canonical writer (canonical_state_bytes)

Example fix

// before
"daily": [["2024-01-01", 10]]
// after
"daily": [{"date": "2024-01-01", "stars": 10}]
Defensive patterns

Strategy: type-guard

Validate before calling

daily = state["reconstruction"]["daily"]
if not all(isinstance(p, dict) for p in daily):
    daily = [{"date": p[0], "stars": p[1]} if isinstance(p, (list, tuple)) else p for p in daily]

Type guard

def are_daily_points_objects(daily: list) -> bool:
    return all(isinstance(p, dict) and set(p) == {"date", "stars"} for p in daily)

Try / catch

try:
    validate_state(state)
except StarHistoryError as exc:
    if "reconstruction point must be an object" in str(exc):
        # locate the offending index via enumerate and re-serialize that point
        ...

Prevention

When it happens

Trigger: validate_state(state) where a daily entry is e.g. ["2024-01-01", 10] (tuple-style array) or a bare integer star count.

Common situations: Producing state from a different language/serializer that emitted arrays instead of objects; hand-editing the daily list; a partially applied data transform.

Related errors


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