{"record":{"id":"41a084090c307cb1","repo":"mvanhorn/last30days-skill","slug":"status-message","errorCode":null,"errorMessage":"{status}: {message}","messagePattern":"\\{status\\}: \\{message\\}","errorType":"http","errorClass":"HtmlPublishError","httpStatus":null,"severity":"error","filePath":"skills/last30days/scripts/lib/html_publish.py","lineNumber":55,"sourceCode":"        raise HtmlPublishError(\"HTML content is empty\")\n\n    payload: dict[str, str] = {\"html_content\": html_content}\n    if password is not None:\n        payload[\"password\"] = password\n\n    request = Request(\n        endpoint,\n        data=json.dumps(payload).encode(\"utf-8\"),\n        headers={\"Content-Type\": \"application/json\", \"Accept\": \"application/json\"},\n        method=\"POST\",\n    )\n    open_fn = opener or urlopen\n    try:\n        with open_fn(request, timeout=timeout) as response:\n            body = response.read().decode(\"utf-8\")\n    except HTTPError as exc:\n        detail = exc.read().decode(\"utf-8\", errors=\"replace\")\n        raise HtmlPublishError(_error_message(exc.code, detail)) from exc\n    except URLError as exc:\n        raise HtmlPublishError(str(exc.reason)) from exc\n    except OSError as exc:\n        raise HtmlPublishError(str(exc)) from exc\n\n    try:\n        result = json.loads(body)\n    except json.JSONDecodeError as exc:\n        raise HtmlPublishError(\"publish endpoint returned non-JSON response\") from exc\n    if not isinstance(result, dict):\n        raise HtmlPublishError(\"publish endpoint returned unexpected JSON response\")\n\n    url = result.get(\"url\")\n    if not isinstance(url, str) or not url.startswith(\"https://\"):\n        raise HtmlPublishError(\"publish endpoint response did not include a valid url\")\n    return result\n\n","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/html_publish.py#L37-L73","documentation":"Raised by publish_html when the HTTP POST to the publish endpoint returns a non-2xx status. The HTTPError body is read and parsed by _error_message(exc.code, detail) into a '{status}: {message}' HtmlPublishError, preserving the provider's own message (e.g. validation failures, wrong password, rate limits). The original HTTPError is chained via 'from exc'.","triggerScenarios":"Uploading an HTML body larger than the endpoint's limit; a wrong or expired 'password' parameter; provider-side 5xx or 429 rate limiting; a custom endpoint= URL that routes to an API that expects a different payload shape.","commonSituations":"Batch-publishing many documents hits a rate limit; the endpoint changed its API contract after an upgrade; a proxy in front of the endpoint returns 4xx (auth required) with an HTML error page as detail.","solutions":["Read the status and provider message: 4xx means fix the request (size, password, payload), 5xx/429 means retry later or with backoff.","If size-related, split or minify the HTML document before publishing.","If auth-related, correct the password parameter or endpoint configuration.","Retry transient failures (429/5xx) with exponential backoff; HtmlPublishError is a single type so branch on the numeric prefix."],"exampleFix":"# before\nresult = publish_html(html)\n\n# after\ntry:\n    result = publish_html(html)\nexcept HtmlPublishError as e:\n    if str(e).startswith((\"429\", \"5\")):\n        time.sleep(backoff); result = publish_html(html)\n    else:\n        raise","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"import re, time\n\nfor attempt in range(3):\n    try:\n        result = publish_html(html, password=pw)\n        break\n    except HtmlPublishError as e:\n        m = re.match(r\"^(\\d{3}):\", str(e))\n        if m and (m.group(1) == \"429\" or m.group(1).startswith(\"5\")):\n            time.sleep(2 ** attempt)\n            continue\n        raise  # 4xx client errors: fix request, never retry","preventionTips":["Branch on the numeric status prefix in the message: 4xx fix request, 429/5xx back off and retry.","Keep documents under the endpoint's size limit; minify before upload.","Log the provider detail string — it names the exact field or limit that failed."],"tags":["network","http","html-publish","api"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}