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_DIMENSIONSView on GitHub (pinned to b5b53acc57)
Solutions
- Regenerate the constant programmatically: base64.b64encode(watermark_png_bytes).decode('ascii') from the reviewed PNG and paste without reformatting.
- Strict-decode check it in isolation before running the pipeline (validate=True).
- Update WATERMARK_LOGO_SHA256 and WATERMARK_LOGO_DIMENSIONS in the same change or error 209 fires next.
- 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
- Generate the watermark base64 programmatically from the reviewed PNG.
- Strict-decode it in a unit test.
- Re-check the literal after any rebranding or merge touching line 61.
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
- reviewed avatar data is invalid
- generated SVG must contain both reviewed images
- Persisted Zep batch does not match the current graph input
- Zep batch {batch_id} acknowledged {len(item_details or [])}
- Zep batch {submission.batch_id} contains {len(items)} items,
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/6d8323d7269953c9.
Report an issue: GitHub.