666ghj/MiroFish · error · StarHistoryError
reconstruction stars must be strictly increasing
Error message
reconstruction stars must be strictly increasing
What it means
Raised by validate_state() when a daily point after the first has stars <= the previous point's stars. Daily star counts are cumulative totals, so they must strictly increase over time; equal or decreasing values indicate corrupted aggregation or unsorted data.
Source
Thrown at scripts/star_history.py:417
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():
raise StarHistoryError("reconstruction must contain only completed UTC dates")
previous_day = point_day
previous_stars = stars
snapshots = state["snapshots"]
if not isinstance(snapshots, list):
raise StarHistoryError("snapshots must be a list")
previous_snapshot: datetime | None = None
first_snapshot: datetime | None = None
for raw_snapshot in snapshots:
if not isinstance(raw_snapshot, dict):
raise StarHistoryError("snapshot must be an object")
_expect_keys(raw_snapshot, {"at", "stars"}, "snapshot")
snapshot_at = _parse_state_timestamp(raw_snapshot["at"], "snapshot.at")
_strict_non_negative_int(raw_snapshot["stars"], "snapshot stars")
if previous_snapshot is not None and snapshot_at <= previous_snapshot:
raise StarHistoryError("snapshot timestamps must be strictly increasing")View on GitHub (pinned to b5b53acc57)
Solutions
- Ensure each daily point stores the cumulative total star count at end of that UTC day, strictly greater than the prior day
- Re-run the reconstruction step to rebuild daily from starred_at data
- If deltas were written, convert them to running totals before validation
Example fix
// before
"daily": [{"date": "2024-01-01", "stars": 100}, {"date": "2024-01-02", "stars": 5}]
// after
"daily": [{"date": "2024-01-01", "stars": 100}, {"date": "2024-01-02", "stars": 105}] Defensive patterns
Strategy: validation
Validate before calling
for i in range(1, len(daily)):
if daily[i]["stars"] <= daily[i - 1]["stars"]:
raise ValueError(f"non-increasing stars at {daily[i]['date']}") Type guard
def stars_strictly_increasing(daily: list) -> bool:
return all(
daily[i]["stars"] > daily[i - 1]["stars"] for i in range(1, len(daily))
) Try / catch
try:
validate_state(state)
except StarHistoryError as exc:
if "reconstruction stars must be strictly increasing" in str(exc):
# rebuild daily as cumulative totals from deltas, then re-validate
... Prevention
- Store cumulative totals, not per-day deltas, in daily
- Validate monotonicity in the producer before persisting
- Re-run reconstruction when GitHub pagination may have dropped data
When it happens
Trigger: validate_state(state) where daily[i]['stars'] <= daily[i-1]['stars'] for i > 0 — e.g. two consecutive days both at 100, or a decreasing value from misordered aggregation.
Common situations: Writing per-day deltas instead of cumulative totals; merging states and averaging/overwriting totals; GitHub pagination issues that dropped stars between fetches.
Related errors
- first reconstruction point must have stars
- {label} must use YYYY-MM-DDTHH:MM:SSZ
- {label} is not a valid UTC timestamp
- {label} contains missing or unknown fields
- history state must be a JSON object
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/c5b07726cc291e9d.
Report an issue: GitHub.