mvanhorn/last30days-skill · error · HtmlPublishError
HTML content is empty
Error message
HTML content is empty
What it means
Raised by publish_html in html_publish.py when html_content is empty or contains only whitespace. The hosted publish endpoint (default https://api.ht-ml.app/v1/sites) would reject an empty document anyway, so the client fails fast before any network I/O. It is an HtmlPublishError (subclass of RuntimeError), the single exception type for the whole publish flow.
Source
Thrown at skills/last30days/scripts/lib/html_publish.py:37
class HtmlPublishBatchResult(dict[str, dict[str, Any]]):
"""Successful document publishes plus an optional later failure."""
def __init__(self) -> None:
super().__init__()
self.error: HtmlPublishError | None = None
def publish_html(
html_content: str,
*,
password: str | None = None,
endpoint: str = DEFAULT_ENDPOINT,
opener: Callable[..., Any] | None = None,
timeout: int = 30,
) -> dict[str, Any]:
"""Publish a single HTML document and return the provider response."""
if not html_content.strip():
raise HtmlPublishError("HTML content is empty")
payload: dict[str, str] = {"html_content": html_content}
if password is not None:
payload["password"] = password
request = Request(
endpoint,
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json", "Accept": "application/json"},
method="POST",
)
open_fn = opener or urlopen
try:
with open_fn(request, timeout=timeout) as response:
body = response.read().decode("utf-8")
except HTTPError as exc:
detail = exc.read().decode("utf-8", errors="replace")
raise HtmlPublishError(_error_message(exc.code, detail)) from excView on GitHub (pinned to c7460f6114)
Solutions
- Check the render output before publishing: if the renderer returned empty, fix the renderer/data rather than the publish call.
- Guard the call site: skip publish when content is blank and surface a clearer upstream error.
- If empty documents are legitimately possible, branch to a fallback page or abort the batch with a specific message.
Example fix
# before
publish_html(rendered) # rendered == ""
# after
if not rendered.strip():
raise RuntimeError("renderer produced empty HTML for this topic")
publish_html(rendered) Defensive patterns
Strategy: validation
Validate before calling
def is_publishable(html: str) -> bool:
return isinstance(html, str) and bool(html.strip()) Type guard
def is_nonempty_html(content: object) -> bool:
return isinstance(content, str) and len(content.strip()) > 0 Try / catch
try:
publish_html(html)
except HtmlPublishError as e:
if str(e) == "HTML content is empty":
# fix the upstream renderer; do not retry the publish
... Prevention
- Make the render stage raise on empty output instead of returning an empty string.
- Assert non-empty content in pipeline code between render and publish.
- Skip optional publishes with a warning rather than letting a blank topic abort a batch.
When it happens
Trigger: Calling publish_html("") or publish_html(" \n"); passing a rendered string from a template that produced nothing (empty topic data, renderer bug); passing a variable that was never assigned because an upstream render step failed silently.
Common situations: A publish step wired into a pipeline where the render stage returned an empty string on failure instead of raising; conditional content that is all-falsy for a given dataset; trailing refactor that renamed the render output variable.
Related errors
- Unknown search source in {flag_name}: {source}
- {flag_name} requires at least one source.
- Unsupported emit mode: {emit}
- [Competitors] --competitors-list is empty.\n
- [Competitors] --competitors must be >= {COMPETITORS_MIN} (go
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/34169fb48f395fbe.
Report an issue: GitHub.