666ghj/MiroFish · error · StarHistoryError

unsupported SVG theme

Error message

unsupported SVG theme

What it means

Raised by `render_svg(state, theme)` at scripts/star_history.py:853 when `theme` is not exactly `"light"` or `"dark"`. The renderer ships two hand-tuned palettes (background/foreground colors etc.) and deliberately rejects anything else, including case variants and locale names, before `validate_state` output is drawn.

Source

Thrown at scripts/star_history.py:853

            f"{_format_float(control1_x)},{_format_float(control1_y)} "
            f"{_format_float(control2_x)},{_format_float(control2_y)} "
            f"{_format_float(x1)},{_format_float(y1)}"
        )
    return "".join(commands)


def render_svg(state: Mapping[str, Any], theme: str) -> bytes:
    """Render the dependency-free Star History-compatible SVG.

    The visual contract is a clean-room Python reimplementation of the MIT
    licensed ``star-history/star-history`` renderer behavior reviewed for this
    setup. No narayann7 JavaScript, npm package, or runtime dependency is
    vendored or executed here.
    """

    validate_state(state)
    if theme not in {"light", "dark"}:
        raise StarHistoryError("unsupported SVG theme")

    width = 800.0
    height = 533.333
    plot_left = 70.0
    plot_top = 60.0
    plot_width = 700.0
    plot_height = 423.333
    plot_bottom = plot_top + plot_height

    if theme == "light":
        background = "#ffffff"
        foreground = "#000000"
        legend_background = "#ffffff"
        line_color = "#dd4528"
    else:
        background = "#0d1117"
        foreground = "#ffffff"
        legend_background = "#0d1117"

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Pass exactly `"light"` or `"dark"` (lowercase, ASCII).
  2. Normalize input before calling: `theme = theme.strip().lower() if isinstance(theme, str) else "light"` restricted to the two allowed values.
  3. If a 'default' theme is requested, map it to "light" at the call site — the renderer has no default branch by design.
  4. Check the caller that constructs the theme string (CLI flag parser, HTTP query param) and constrain it to a choices=["light","dark"] argument.

Example fix

# before
svg = render_svg(state, theme=request.args.get("theme", "default"))  # raises

# after
THEMES = {"light", "dark"}
theme = request.args.get("theme", "light").strip().lower()
if theme not in THEMES:
    theme = "light"
svg = render_svg(state, theme=theme)
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED_THEMES = {"light", "dark"}
theme = theme if theme in ALLOWED_THEMES else "light"  # or reject explicitly
svg = render_svg(state, theme)

Type guard

def is_supported_theme(value: object) -> TypeGuard[str]:
    return isinstance(value, str) and value in {"light", "dark"}

Try / catch

try:
    svg = render_svg(state, theme)
except StarHistoryError as exc:
    if "unsupported SVG theme" in str(exc):
        svg = render_svg(state, "light")  # explicit fallback choice
    else:
        raise

Prevention

When it happens

Trigger: Calling `render_svg(state, theme)` with e.g. `"Dark"`, `"dark-mode"`, `""`, `None`, or a theme read from config/CLI argv without normalization. The check is a set membership test `theme not in {"light", "dark"}` — case-sensitive.

Common situations: Wrapping the script in CI or a badge service that passes `?theme=Dark` or `theme=default`; wiring the theme from an environment variable with different casing; new callers assuming arbitrary theme strings are supported.

Related errors


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