{"record":{"id":"6f6ca5fdbc931d62","repo":"666ghj/MiroFish","slug":"reviewed-avatar-data-is-invalid","errorCode":null,"errorMessage":"reviewed avatar data is invalid","messagePattern":"reviewed avatar data is invalid","errorType":"exception","errorClass":"StarHistoryError","httpStatus":null,"severity":"error","filePath":"scripts/star_history.py","lineNumber":1253,"sourceCode":"                if local_name != \"image\" or value not in {\n                    OWNER_AVATAR_DATA_URI,\n                    WATERMARK_LOGO_DATA_URI,\n                }:\n                    raise StarHistoryError(\"generated SVG contains an external resource\")\n            lowered = value.lower().replace(\" \", \"\")\n            if \"url(\" in lowered and lowered not in {\n                \"url(#xkcdify)\",\n                \"url(#clip-circle-title)\",\n            }:\n                raise StarHistoryError(\"generated SVG contains an external resource\")\n            if lowered.startswith((\"http:\", \"https:\", \"//\")):\n                raise StarHistoryError(\"generated SVG contains an external resource\")\n    if avatar_count != 1 or watermark_count != 1:\n        raise StarHistoryError(\"generated SVG must contain both reviewed images\")\n    try:\n        avatar = base64.b64decode(OWNER_AVATAR_BASE64, validate=True)\n    except ValueError as exc:\n        raise StarHistoryError(\"reviewed avatar data is invalid\") from exc\n    if (\n        len(avatar) > MAX_INLINE_AVATAR_BYTES\n        or hashlib.sha256(avatar).hexdigest() != OWNER_AVATAR_SHA256\n        or _reviewed_avatar_dimensions(avatar) != OWNER_AVATAR_DIMENSIONS\n    ):\n        raise StarHistoryError(\"reviewed avatar data is invalid\")\n    try:\n        watermark = base64.b64decode(WATERMARK_LOGO_BASE64, validate=True)\n    except ValueError as exc:\n        raise StarHistoryError(\"reviewed watermark data is invalid\") from exc\n    png_header = (\n        watermark.startswith(b\"\\x89PNG\\r\\n\\x1a\\n\")\n        and watermark[8:12] == (13).to_bytes(4, \"big\")\n        and watermark[12:16] == b\"IHDR\"\n        and len(watermark) >= 33\n    )\n    watermark_dimensions = (\n        (","sourceCodeStart":1235,"sourceCodeEnd":1271,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/scripts/star_history.py#L1235-L1271","documentation":"Raised by _validate_svg when base64.b64decode(OWNER_AVATAR_BASE64, validate=True) throws ValueError — the hard-coded avatar constant is not valid strict base64. This validates the script's own embedded constants (not user input), so hitting it means the source constant was corrupted or malformed during an edit. The original exception is chained via 'from exc'.","triggerScenarios":"Editing OWNER_AVATAR_BASE64 (scripts/star_history.py:49) by hand: whitespace/newlines inserted, a character outside the base64 alphabet, wrong padding, or a truncated copy-paste of the JPEG's base64. validate=True makes b64decode reject any non-alphabet byte.","commonSituations":"Replacing the owner avatar: pasting base64 from a website that wraps lines or URL-safe-encodes (-/_ instead of +//); truncation by an editor or diff tool; a bad merge conflict resolution inside the giant string literal.","solutions":["Regenerate the constant programmatically from the actual image file: base64.b64encode(path.read_bytes()).decode('ascii') with no reformatting, and paste it verbatim.","Verify with python -c \"import base64;base64.b64decode(open(...).read(), validate=True)\" style strict decoding before running the script.","Update the paired constants in the same commit: OWNER_AVATAR_SHA256 and OWNER_AVATAR_DIMENSIONS (64x64), else error 207 fires next.","Check the git diff of line 49 for merge-conflict artifacts or line wrapping."],"exampleFix":"# before: hand-pasted, line-wrapped base64\nOWNER_AVATAR_BASE64 = \"/9j/2wCEAAgGBgcG...\nCAgGBgcG...\"  # wraps/typos -> ValueError\n\n# after: generate atomically from the reviewed file\nimport base64, pathlib\nOWNER_AVATAR_BASE64 = base64.b64encode(\n    pathlib.Path(\"assets/owner-avatar-64.jpg\").read_bytes()\n).decode(\"ascii\")","handlingStrategy":"validation","validationCode":"import base64\n\ntry:\n    base64.b64decode(OWNER_AVATAR_BASE64, validate=True)\nexcept ValueError:\n    raise SystemExit(\"OWNER_AVATAR_BASE64 is not strict base64; regenerate it\")","typeGuard":null,"tryCatchPattern":"try:\n    _validate_svg(svg_bytes)\nexcept StarHistoryError as exc:\n    if \"avatar data is invalid\" in str(exc) and isinstance(exc.__cause__, ValueError):\n        # the base64 literal itself is malformed; regenerate it from the source image\n        ...","preventionTips":["Generate base64 constants programmatically, never hand-type them.","Strict-decode constants in a unit test so corruption is caught before runtime.","Watch merges around the long string literals at scripts/star_history.py:49 and :61."],"tags":["base64","assets","avatar","data-integrity"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}