diff --git a/oxi/exception.py b/oxi/exception.py
index 614627d..be3adaf 100644
--- a/oxi/exception.py
+++ b/oxi/exception.py
@@ -13,10 +13,32 @@ _STATUS_MESSAGES: dict[int, str] = {
}
+def _looks_like_node_not_found_html(e: "HTTPError") -> bool:
+ resp = getattr(e, "response", None)
+ if resp is None:
+ return False
+ try:
+ content_type = (resp.headers or {}).get("Content-Type", "")
+ except Exception:
+ content_type = ""
+ if "text/html" not in (content_type or "").lower():
+ return False
+ try:
+ body = (resp.text or "")[:20_000]
+ except Exception:
+ return False
+ return (
+ "Oxidized::NodeNotFound" in body
+ or "NodeNotFound" in body
+ or "
Oxidized::NodeNotFound" in body
+ )
+
+
class OxiAPIError(Exception):
def __init__(self, message: str, status_code: Optional[int] = None):
super().__init__(message)
self.status_code = status_code
+ self.message = message
def __str__(self):
if self.status_code is not None:
@@ -25,10 +47,19 @@ class OxiAPIError(Exception):
@classmethod
def from_http_error(cls, e: "HTTPError", context: str = "") -> "OxiAPIError":
- status = e.response.status_code
+ resp = getattr(e, "response", None)
+ status = resp.status_code if resp is not None else None
+
+ if status == 500 and _looks_like_node_not_found_html(e):
+ status = 404
+
if status == 404:
message = f"{context} not found" if context else "Not found"
else:
- base = _STATUS_MESSAGES.get(status) or e.response.reason or f"HTTP {status}"
+ base = (
+ (_STATUS_MESSAGES.get(status) if status is not None else None)
+ or (resp.reason if resp is not None else None)
+ or (f"HTTP {status}" if status is not None else "Request failed")
+ )
message = f"{context}: {base}" if context else base
return cls(message, status)