666ghj/MiroFish · error · StarHistoryError

aggregate-only history cannot contain reconstructed dates

Error message

aggregate-only history cannot contain reconstructed dates

What it means

Raised by validate_state() when reconstruction.method is 'aggregate_snapshot_only' yet the daily list is non-empty. An aggregate-only history intentionally carries no reconstructed daily points; its star history is derived purely from snapshots. Mixing both is treated as a corrupt or contradictory state.

Source

Thrown at scripts/star_history.py:394

    _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:
        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:

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Either set method to 'current_stargazers_starred_at' (keeping the daily points), or set daily to [] for aggregate_snapshot_only
  2. Do not hand-switch methods on an existing state file; regenerate it with the intended mode

Example fix

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

Strategy: validation

Validate before calling

method = state["reconstruction"]["method"]
daily = state["reconstruction"]["daily"]
if method == "aggregate_snapshot_only" and daily:
    state["reconstruction"]["daily"] = []  # or switch method if daily is authoritative

Type guard

def is_method_daily_consistent(method: str, daily: list) -> bool:
    return not (method == "aggregate_snapshot_only" and daily)

Try / catch

try:
    validate_state(state)
except StarHistoryError as exc:
    if "aggregate-only history cannot contain reconstructed dates" in str(exc):
        # decide which source is authoritative and rebuild the state
        ...

Prevention

When it happens

Trigger: validate_state(state) with method="aggregate_snapshot_only" and at least one entry in reconstruction.daily.

Common situations: Switching a state file from the reconstructed method to aggregate_snapshot_only by editing only the method field while leaving daily data in place; merging states from two runs that used different methods.

Related errors


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