#223
The Incident: A Complete Silent Reject Story on Blogger Themes
When operating a customized Blogger theme, the Developer Console or automated CDP scripts might upload a newly designed theme XML successfully. The Blogger Dashboard pops up a "Theme updated successfully" toast message, but upon refreshing the live website, the changes are nowhere to be seen. You clear your cache, try incognito windows, check other devices—still, the old theme persists. We spent three agonizing days debugging this mystery, only to discover the root cause was a single comment token.
Step 1: Round-Trip Verification & Silent Reject Concept
To identify the issue, we wrote a test harness inside our Playwright environment to fetch the theme source code via Blogger's CodeMirror editor. Specifically, we called CodeMirror.getValue() to inspect the actual XML stored in the backend and compared it byte-for-byte with our uploaded local file. The comparison revealed that Blogger silently discarded parts of our XML code. Crucially, the Blogger administration UI still displayed the success notification, offering absolutely zero warnings or error codes about the rejection.
Step 2: Differential Analysis & CSS CDATA Parser Quirks
A rigorous diff between our local file and the backend-stored XML showed that the discrepancy occurred inside the <b:skin> element's CDATA section. Specifically, inside a standard CSS comment, we had left a helpful note:
/* sess113 antigravity light hero — applies to <body class="ag-home"> only */
This innocent comment broke the Blogger SkinVariables parser. While XML CDATA is technically supposed to accept any raw text, Blogger's theme compiler scans the contents of <b:skin><![CDATA[...]]></b:skin> for potential security threats. If it encounters raw HTML element tokens like <body>, <html>, or <script>—even inside CSS comments—it silently aborts the update and rejects the theme to prevent XSS vulnerability attacks.
The Fix & Prevention Lint Script
To resolve the issue, we simply swapped the raw HTML tokens in our comments with clear natural language descriptions:
/* applies to home body when ag-home class is set */
To ensure this silent reject never disrupts our workflow again, we implemented an automated pre-flight linting script inside our deployment pipeline:
import re
DANGEROUS_TOKENS = [
r'<html\b', r'<body\b', r'<head\b',
r'<script\b', r'<iframe\b',
]
def lint_skin_cdata(xml: str) -> list[str]:
skin_m = re.search(r'<b:skin>\s*<!\[CDATA\[(.*?)\]\]>\s*</b:skin>', xml, re.DOTALL)
if not skin_m: return []
css = skin_m.group(1)
findings = []
for cm in re.finditer(r'/\*.*?\*/', css, re.DOTALL):
comment = cm.group(0)
for tok in DANGEROUS_TOKENS:
if re.search(tok, comment, re.I):
findings.append(f"Dangerous token detected inside comment: {tok}")
return findings
Since we integrated this linting safety check into our automated uploading script, our theme updates have had a 100% success rate with zero silent rejections.