666ghj/MiroFish · error · StarHistoryError

reviewed watermark data is invalid

Error message

reviewed watermark data is invalid

What it means

Raised by _validate_svg when base64.b64decode(WATERMARK_LOGO_BASE64, validate=True) throws ValueError — the hard-coded watermark constant (scripts/star_history.py:61) is not strict base64. Like error 206, this is self-validation of the script's embedded constants, so it fires only when that literal was corrupted or hand-edited; the ValueError is chained as the cause.

Source

Thrown at scripts/star_history.py:1263

                raise StarHistoryError("generated SVG contains an external resource")
            if lowered.startswith(("http:", "https:", "//")):
                raise StarHistoryError("generated SVG contains an external resource")
    if avatar_count != 1 or watermark_count != 1:
        raise StarHistoryError("generated SVG must contain both reviewed images")
    try:
        avatar = base64.b64decode(OWNER_AVATAR_BASE64, validate=True)
    except ValueError as exc:
        raise StarHistoryError("reviewed avatar data is invalid") from exc
    if (
        len(avatar) > MAX_INLINE_AVATAR_BYTES
        or hashlib.sha256(avatar).hexdigest() != OWNER_AVATAR_SHA256
        or _reviewed_avatar_dimensions(avatar) != OWNER_AVATAR_DIMENSIONS
    ):
        raise StarHistoryError("reviewed avatar data is invalid")
    try:
        watermark = base64.b64decode(WATERMARK_LOGO_BASE64, validate=True)
    except ValueError as exc:
        raise StarHistoryError("reviewed watermark data is invalid") from exc
    png_header = (
        watermark.startswith(b"\x89PNG\r\n\x1a\n")
        and watermark[8:12] == (13).to_bytes(4, "big")
        and watermark[12:16] == b"IHDR"
        and len(watermark) >= 33
    )
    watermark_dimensions = (
        (
            int.from_bytes(watermark[16:20], "big"),
            int.from_bytes(watermark[20:24], "big"),
        )
        if png_header
        else None
    )
    if (
        len(watermark) > MAX_INLINE_WATERMARK_BYTES
        or not png_header
        or watermark_dimensions != WATERMARK_LOGO_DIMENSIONS

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Regenerate the constant programmatically: base64.b64encode(watermark_png_bytes).decode('ascii') from the reviewed PNG and paste without reformatting.
  2. Strict-decode check it in isolation before running the pipeline (validate=True).
  3. Update WATERMARK_LOGO_SHA256 and WATERMARK_LOGO_DIMENSIONS in the same change or error 209 fires next.
  4. Inspect git diff around line 61 for wrapping or conflict markers.

Example fix

# before: wrapped/edited literal
WATERMARK_LOGO_BASE64 = (
    "iVBORw0KGgoAAAANSUhEUg..."   # hand-truncated
)

# after: single atomic regeneration
WATERMARK_LOGO_BASE64 = base64.b64encode(
    pathlib.Path("assets/watermark-64.png").read_bytes()
).decode("ascii")
Defensive patterns

Strategy: validation

Validate before calling

import base64

try:
    base64.b64decode(WATERMARK_LOGO_BASE64, validate=True)
except ValueError:
    raise SystemExit("WATERMARK_LOGO_BASE64 is not strict base64; regenerate it")

Try / catch

try:
    _validate_svg(svg_bytes)
except StarHistoryError as exc:
    if "watermark data is invalid" in str(exc) and isinstance(exc.__cause__, ValueError):
        # the watermark base64 literal is malformed; regenerate from the source PNG
        ...

Prevention

When it happens

Trigger: Hand-editing WATERMARK_LOGO_BASE64: inserted whitespace/newlines, URL-safe alphabet characters, wrong padding, truncated paste, or merge-conflict residue inside the multi-line string literal.

Common situations: Rebranding the star-history.com watermark; copying base64 from a tool that wraps at 76 columns or percent-escapes characters; a bad merge on the long constant block.

Related errors


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