mvanhorn/last30days-skill · error · HtmlPublishError
{exc.reason}
Error message
{exc.reason} What it means
Raised by publish_html when the request fails before getting an HTTP response and the underlying exception is a urllib URLError — the message is str(exc.reason), the inner cause (DNS failure, connection refused, SSL error, timeout during connect). Chained as 'from exc' so the full traceback still shows the URLError.
Solutions
- Verify basic connectivity: curl -I https://api.ht-ml.app/v1/sites (or your custom endpoint).
- For custom endpoints, confirm the local/remote server is up and the URL scheme/port are right.
- In proxied environments, export HTTPS_PROXY and ensure the proxy CA is trusted.
- Treat as transient only if the network is flaky; DNS/connection-refused usually means environment, not provider.
Example fix
# before
result = publish_html(html)
# after
import socket
try:
result = publish_html(html)
except HtmlPublishError as e:
if isinstance(e.__cause__, URLError) and isinstance(e.__cause__.reason, (socket.gaierror, ConnectionRefusedError)):
log.warning("endpoint unreachable: %s", e)
result = None Defensive patterns
Strategy: retry
Validate before calling
import socket
def endpoint_reachable(host: str, port: int = 443, timeout: float = 5.0) -> bool:
try:
socket.create_connection((host, port), timeout=timeout).close()
return True
except OSError:
return False Try / catch
from urllib.error import URLError
try:
publish_html(html)
except HtmlPublishError as e:
if isinstance(e.__cause__, URLError):
reason = e.__cause__.reason
# DNS failure / refused / SSL -> environment problem; fix network, do not blind-retry
log.error("publish endpoint unreachable: %s", reason) Prevention
- Check e.__cause__ to classify: gaierror (DNS), ConnectionRefusedError (server down), ssl errors (TLS/CA).
- In containers/CI, verify egress to api.ht-ml.app:443 before running publish steps.
- Set HTTPS_PROXY and trust the proxy CA in corporate networks.
When it happens
Trigger: No network / offline machine; DNS cannot resolve api.ht-ml.app (or the custom endpoint host); a firewall or proxy blocks outbound HTTPS; TLS certificate verification fails; endpoint port closed.
Common situations: Running inside a container or CI runner without network egress; corporate MITM proxy with an untrusted CA; airplane-mode laptop; a custom endpoint= pointing at a local server that is not running yet (connection refused).
Related errors
- {exc}
- publish endpoint returned non-JSON response
- {status}: {message}
- All X backends failed
- Gemini request failed
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/2926cc8915d20f1a.
Report an issue: GitHub.
Appendix: source
Thrown at skills/last30days/scripts/lib/html_publish.py:57
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 exc
except URLError as exc:
raise HtmlPublishError(str(exc.reason)) from exc
except OSError as exc:
raise HtmlPublishError(str(exc)) from exc
try:
result = json.loads(body)
except json.JSONDecodeError as exc:
raise HtmlPublishError("publish endpoint returned non-JSON response") from exc
if not isinstance(result, dict):
raise HtmlPublishError("publish endpoint returned unexpected JSON response")
url = result.get("url")
if not isinstance(url, str) or not url.startswith("https://"):
raise HtmlPublishError("publish endpoint response did not include a valid url")
return result
def publish_html_documents(
documents: Mapping[str, str],View on GitHub (pinned to c7460f6114)