fix(vedastro): cut responses are network errors, not 500 (BUG-1504)

_post_json turns IncompleteRead, ConnectionResetError, RemoteDisconnected and
ssl.SSLError raised while reading into URLError, so snapshot dispatch, range
scan and external technique evidence record network_error. The REST health
probe also catches http.client.HTTPException.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
This commit is contained in:
2026-11-02 07:50:02 +08:00
co-authored by Claude Opus 5.5
parent ba1b4be71d
commit 87765d602c
2 changed files with 19 additions and 4 deletions
+3 -1
View File
@@ -13,6 +13,7 @@ and remains ``official_blocked``.
from __future__ import annotations
import argparse
import http.client
import json
import os
import sys
@@ -155,7 +156,8 @@ def probe_calculate_health(*, opener: Any | None = None, timeout: float = 8) ->
"endpoint": API,
"transport": "rest",
}
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError, OSError) as error:
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError, OSError, http.client.HTTPException) as error:
# HTTPException: IncompleteRead and friends when the body is cut (BUG-1504).
return {
"status": "official_blocked",
"reason": type(error).__name__,
+16 -3
View File
@@ -14,6 +14,7 @@ import hashlib
import json
import os
import socket
import ssl
import subprocess
import sys
import threading
@@ -2016,6 +2017,12 @@ def _acquire_free_tier_slot(request_url: str) -> dict[str, Any]:
}
# A connection cut while reading headers or the body. urllib only wraps errors
# raised while sending, so these reach the caller raw (BUG-1504). RemoteDisconnected
# is both an HTTPException and a ConnectionResetError.
_TRANSPORT_READ_ERRORS = (http.client.HTTPException, ConnectionError, ssl.SSLError)
def _post_json(endpoint: str, request_preview: dict[str, Any]) -> dict[str, Any] | str:
request_url, headers, vedastro_payload = _build_live_request(endpoint, request_preview)
req = request.Request(
@@ -2024,9 +2031,15 @@ def _post_json(endpoint: str, request_preview: dict[str, Any]) -> dict[str, Any]
headers=headers,
method="POST",
)
with request.urlopen(req, timeout=_timeout_seconds()) as resp:
raw = resp.read().decode("utf-8")
return json.loads(raw)
try:
with request.urlopen(req, timeout=_timeout_seconds()) as resp:
raw = resp.read().decode("utf-8")
except error.URLError:
raise
except _TRANSPORT_READ_ERRORS as exc:
# Every caller already turns URLError into network_error.
raise error.URLError(f"response_read_failed:{type(exc).__name__}") from exc
return json.loads(raw)
def _retry_status_codes() -> set[int]: