Report a short provider error code when a model call fails
Cause
When the model API returns an error, post_json() only says Model provider returned HTTP 400; no action executed. A TypeSafe rejection for request size (max_tokens_exceeded) and an invalid key produce the same message, so users cannot tell why the call failed. A connection failure only says Model connection failed, so a timeout looks the same as a refused connection.
Changes
- The error code is read from the JSON error body and appended, as in
HTTP 400 (max_tokens_exceeded). Only two places are read: TypeSafe'sdetail.error_type(the real response is{"detail":{"error_type":"max_tokens_exceeded"}}) and the OpenAI-styleerror.code(falling back toerror.type) used for text generation. A value is used only when it looks like a short identifier ([A-Za-z0-9_.:-]{1,100}). The response body,messageand credentials are never shown. Message-only responses such as{"detail":"Too many choices. …"}and non-JSON responses keep only the HTTP status, as before. - A connection failure now names the exception type, such as
ReadTimeout. The exception message is still not chained (from None). - One sentence added to the Development section of the README.
#37 also changes the error handling in post_json() (it keeps the response body on the exception). This PR only adds a short code to the message, so whichever lands first, the rebase of the other is small.
Tests
- 11 tests added: the TypeSafe code,
messagenot shown, a message-onlydetail, an unlisteddetail.codenot shown, the OpenAI code and the fallback from a numeric code totype, rejecting values with spaces and unstructured errors, non-JSON responses, and aReadTimeoutthat shows its type but not its message and is not chained. uv run ruff check .anduv run pytestpass on macOS, Linux and Windows 11. On Windows they were run withPYTHONUTF8=1because of the known cp932 failure when upstreammainreadssnapshot.js(#5). The follow-up commit a5ef60c (reading onlydetail.error_type, from the review below) was tested on Linux: 42 passed.- Real requests to TypeSafe (
/v1/systemone) throughpost_json()show:- Invalid key:
Model provider returned HTTP 401 (authentication_error); no action executed. - A request of about 570 KB:
Model provider returned HTTP 400 (max_tokens_exceeded); no action executed.
- Invalid key:
🤖 Generated with Claude Code
Summary by cubic
Model API failures now report a short provider error code (e.g. max_tokens_exceeded) alongside the HTTP status, and connection failures report the exception type (e.g. ReadTimeout), so users can tell why a call failed.
- Reads the code from TypeSafe's
detail.error_typeor an OpenAI-styleerror.code/error.type, only when it is a short identifier. - Never includes the response body,
message, or credentials; non-JSON and message-only responses keep just the HTTP status. Connection failure details are not chained. - Adds 11 tests covering code extraction, sanitization, non-JSON responses, and timeout handling, plus a note in the README's Development section.