Fix: extend ChatEngine HTTP-status mapping to Anthropic /messages and Open Responses /responses#6
Draft
mimeding wants to merge 2 commits into
Draft
Conversation
The non-streaming /v1/chat/completions endpoint was already taught (PR osaurus-ai#863) to translate ChatEngine.EngineError into its intended HTTP status: 404 when the requested model isn't installed, 503 when the provider that handles it is unavailable, etc. The matching Anthropic /messages and Open Responses /responses endpoints, both of which run the same ChatEngine, were still hardcoded to 500 on every error. That meant API clients calling those endpoints couldn't distinguish 'install the model' from 'restart the local server' from 'the remote provider is offline,' and the WorkView error classifier — which uses the HTTP status to decide what to show the user — defaulted to the catch-all 5xx message. Mirror the /v1/chat/completions pattern in both handlers: * Translate EngineError -> httpStatus on the wire response head. * Pick the appropriate provider-native error_type/code (Anthropic's invalid_request_error vs api_error, Open Responses' two-tier code field) based on whether the status is 4xx or 5xx. * Log responseStatus: Int(status.code) instead of hardcoded 500 so the Insights tab matches the wire response. Other failure modes (network errors, decoder errors) still fall through to .internalServerError exactly as before; only EngineError gets the new mapping. The wire body shape is unchanged — same AnthropicError / OpenResponsesErrorResponse types, same JSON keys. Co-authored-by: Michael Meding <mimeding@users.noreply.github.com>
This was referenced May 27, 2026
ModelManager.init kicks off an unstructured Task that calls loadOsaurusAIOrgModels(), which fetches the OsaurusAI organization listing from Hugging Face and feeds the result through applyOsaurusOrgFetch. The unit-test runner repeatedly constructs ModelManager() to drive applyOsaurusOrgFetch directly. The background launch-time fetch races with those test calls — whichever finishes last wins, and the merge result is non-deterministic. That's the root cause of the flaky ModelManagerSuggestedTests failures seen across many of the recent PR CI runs (applyOsaurusOrgFetch_dropsStaleAutoFetched OnReapply, applyOsaurusOrgFetch_addsNewEntriesAfterCurated, etc.). Gate the launch-time fetch on a small isRunningInTestEnvironment helper that checks for any of XCTestConfigurationFilePath, XCTestBundlePath, or XCTestSessionIdentifier in the process environment. Those variables are only present inside an xctest host process; production app launches still get the HF fetch exactly as before. This is a network call, so removing it under tests also has the side benefit of making the test suite work offline / on hermetic CI runners. Co-authored-by: Michael Meding <mimeding@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why this matters (business)
Osaurus exposes the same local model behind three OpenAI-style endpoints (
/v1/chat/completions, Anthropic-compatible/messages, OpenAI Responses-API/responses). PR osaurus-ai#863 taught one of them —/v1/chat/completions— to return the right HTTP status for ChatEngine errors:The matching Anthropic and Open Responses handlers, which run on the same
ChatEngine, kept returning blanket 500 Internal Server Error for every failure mode. That has three concrete user-visible effects:This PR brings API parity to the three endpoints.
What's wrong (technical)
The
/v1/chat/completionsnon-streaming handler already mapsChatEngine.EngineError -> httpStatus:Anthropic non-stream
/messagesdid not:Open Responses non-stream
/responsesdid not:ChatEngine.EngineErroralready exposeshttpStatus: Intand a human-readableerrorDescription. Both handlers need to consume it.Fix
Both non-streaming error paths now:
EngineErrorto the right HTTP status on the wire (Int(httpStatus)).invalid_request_errorfor client errors andapi_errorfor server faults; Open Responses uses the same pair under itscodefield.responseStatus: Int(status.code)(matching PR Fix: /chat/completions logs status 500 even when the wire status is 404/503 #2) so the Insights row matches the wire response.Errors that are not
ChatEngine.EngineError(network failure, decoder failure, anything thrown by tool execution) still fall through to.internalServerError. Wire body shape is unchanged — sameAnthropicError/OpenResponsesErrorResponsetypes, same JSON keys; only the values oftype/codeand the HTTP head change.Scope decisions
/v1/chat/completions//messages//responsespaths were also flagged in the audit (they always log 500 even though the wire status is the committed-200 of the SSE head). They have a real architectural quirk — once SSE is committed, you can't change the status — and need a separate, focused discussion. Left untouched here./chatand/api/chatfollow the same SSE-committed pattern and are also out of scope.Changes
/v1/chat/completions)Test Plan
Checklist
CONTRIBUTING.mdswiftc -frontend -parseof the modified file)