666ghj/MiroFish · error · StarHistoryError
chart coordinates must be finite
Error message
chart coordinates must be finite
What it means
Raised in `_monotone_x_path` (scripts/star_history.py:786), the D3-curveMonotoneX-equivalent SVG path builder used by `render_svg`. Every (x, y) chart point must be a finite float; NaN or ±infinity cannot be serialized into valid SVG path coordinates and would poison the Steffen monotonic interpolation.
Source
Thrown at scripts/star_history.py:786
if value < 0:
return -1
if value > 0:
return 1
return 0
def _monotone_x_path(points: Sequence[tuple[float, float]]) -> str:
"""Return a D3 curveMonotoneX-equivalent SVG path.
D3 uses Steffen monotonic interpolation: interior tangents are limited so a
smooth cubic cannot overshoot a monotonic run. This small implementation
keeps the Star History curve shape without adding a JavaScript dependency.
"""
normalized: list[tuple[float, float]] = []
for x, y in points:
if not math.isfinite(x) or not math.isfinite(y):
raise StarHistoryError("chart coordinates must be finite")
if normalized and x < normalized[-1][0]:
raise StarHistoryError("chart coordinates must be ordered")
if normalized and x == normalized[-1][0]:
normalized[-1] = (x, y)
else:
normalized.append((x, y))
if not normalized:
return ""
start_x, start_y = normalized[0]
commands = [f"M{_format_float(start_x)},{_format_float(start_y)}"]
if len(normalized) == 1:
return "".join(commands)
if len(normalized) == 2:
end_x, end_y = normalized[1]
commands.append(f"L{_format_float(end_x)},{_format_float(end_y)}")
return "".join(commands)View on GitHub (pinned to b5b53acc57)
Solutions
- Run `validate_state(state)` on the exact state object before `render_svg` — the public renderer does this too, so a hit means the bad value appears only after scaling; check the state file for odd dates or star counts.
- If you call `_monotone_x_path` directly, filter/replace non-finite points first: `pts = [(x, y) for x, y in pts if math.isfinite(x) and math.isfinite(y)]`.
- In forked scaling code, guard degenerate ranges (`if x_max == x_min: x_max = x_min + 1`) so no inf emerges from division.
- Rebuild the state from a fresh backfill/snapshot if the file was hand-edited.
Example fix
# before: passing raw computed points path = _monotone_x_path(scaled_points) # may contain nan/inf -> raises # after: sanitize before calling scaled_points = [(x, y) for x, y in scaled_points if math.isfinite(x) and math.isfinite(y)] path = _monotone_x_path(scaled_points)
Defensive patterns
Strategy: validation
Validate before calling
import math
def finite_points(points):
return all(math.isfinite(x) and math.isfinite(y) for x, y in points)
assert finite_points(scaled_points), "chart math produced non-finite coordinates"
path = _monotone_x_path(scaled_points) Try / catch
try:
svg = render_svg(state, theme)
except StarHistoryError as exc:
if "must be finite" in str(exc):
raise ValueError("state produced non-finite chart coordinates; regenerate state") from exc
raise Prevention
- Only render state produced by the library's own builders — validate_state plus the chart pipeline keep coordinates finite by construction.
- If you fork the axis scaling, add guards for degenerate ranges (max==min) that would divide by zero.
- Never hand-edit star counts or dates in the state JSON to sentinel values like null/'NaN'.
When it happens
Trigger: `render_svg(state, theme)` reaching the path builder with a point whose x or y is NaN/inf. Points derive from `_chart_points(state)` (dates as x via matplotlib-style date numbers, stars as y) followed by axis scaling — non-finite values appear when state contains corrupt dates/stars that slipped past `validate_state`, or when custom code calls `_monotone_x_path` directly with computed coordinates that divide by zero (e.g. scale = 1/(max-min) with max==min).
Common situations: Hand-edited state JSON with nulls coerced to NaN upstream; a fork that changes chart scaling and introduces a zero-denominator; direct use of the private path helper in other tooling with unfiltered data.
Related errors
- chart coordinates must be ordered
- unsupported SVG theme
- generated SVG contains a forbidden element
- generated SVG contains an unsafe attribute value
- GitHub GraphQL returned no pages
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/4700432138fb7287.
Report an issue: GitHub.