666ghj/MiroFish · error · StarHistoryError
snapshot timestamps must be strictly increasing
Error message
snapshot timestamps must be strictly increasing
What it means
Raised by validate_state() when snapshot 'at' timestamps are not strictly increasing across the snapshots array (a duplicate or out-of-order timestamp fails). Snapshots are appended once per INTERVAL_DAYS run, so order reflects chronological append order.
Source
Thrown at scripts/star_history.py:435
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")
if first_snapshot is None:
first_snapshot = snapshot_at
previous_snapshot = snapshot_at
if first_snapshot is not None:
if first_snapshot < generated_at:
raise StarHistoryError("first snapshot cannot predate reconstruction")
if previous_day is not None and previous_day >= first_snapshot.date():
raise StarHistoryError("reconstruction dates must predate snapshots")
def canonical_state_bytes(state: Mapping[str, Any]) -> bytes:
validate_state(state)
return (
json.dumps(state, ensure_ascii=False, indent=2, sort_keys=True) + "\n"
).encode("utf-8")
View on GitHub (pinned to b5b53acc57)
Solutions
- Sort snapshots by 'at' ascending and remove duplicate timestamps before writing state
- When merging histories, dedupe on 'at' keeping the latest write
- Re-run the snapshot interval to append a fresh, later timestamp
Example fix
# before
snapshots = snapshots + merged_snapshots # unsorted concat
# after
snapshots = sorted({s["at"]: s for s in snapshots + merged_snapshots}.values(), key=lambda s: s["at"]) Defensive patterns
Strategy: validation
Validate before calling
snaps = sorted({s["at"]: s for s in snaps}.values(), key=lambda s: s["at"]) Type guard
def snapshot_timestamps_increasing(snaps: list) -> bool:
return all(snaps[i]["at"] < snaps[i + 1]["at"] for i in range(len(snaps) - 1)) Try / catch
try:
validate_state(state)
except StarHistoryError as exc:
if "snapshot timestamps must be strictly increasing" in str(exc):
# sort by 'at' and deduplicate timestamps, then re-validate
... Prevention
- Append snapshots chronologically; never reorder the array
- Deduplicate on 'at' when merging state files
- Ensure the run clock is UTC to avoid skewed timestamps
When it happens
Trigger: validate_state(state) where snapshots[i]['at'] <= snapshots[i-1]['at'] — e.g. two snapshots with identical timestamps or a list sorted by stars instead of time.
Common situations: Merging state files by naive concatenation without re-sorting; a state rewrite that lost ordering; clock skew causing an equal or earlier timestamp on a later run.
Related errors
- reconstruction dates must be strictly increasing
- {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/8973e32072bc48e9.
Report an issue: GitHub.