Repository navigation
fix(sse): keep HTTP status and retry hint in post-keepalive /v1/responses error frames - #14632
Merged
diegosouzapw merged 1 commit intoSep 24, 2026
Conversation
QuangBlue
force-pushed
the
fix/responses-error-frame-status
branch
from
September 23, 2026 11:55
03a3194 to
df0180f
Compare
…nses error frames
Once withEarlyStreamKeepalive commits /v1/responses to HTTP 200, a handler error
response is framed as {type:error, code, message, param}. The HTTP status,
Retry-After and error.type were dropped, so clients could not tell a permanent
failure (403 model not allowed) from a transient one (429/503) and retried
permanent errors. The frame now also carries status_code, error_type and
retry_after_seconds (Retry-After or x-omniroute-retry-after-seconds, clamped
to 0..3600). Chat and Anthropic frames and the fast path are unchanged.
Follow-up of diegosouzapw#13431.
QuangBlue
force-pushed
the
fix/responses-error-frame-status
branch
from
September 24, 2026 03:06
df0180f to
ab0353a
Compare
Owner
|
Nice fix — the design notes on |
Contributor
Author
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.
Symptom
/v1/responsesstreaming requests that go through the early keepalive (#13431) are committed toHTTP 200 after
DEFAULT_THRESHOLD_MS. When the handler then returns an error response (forexample a 403 "model not allowed for this key", a 429 with
Retry-After, or a 503), the clientreceives a single
{"type":"error", code, message, param, sequence_number}frame. The HTTPstatus, the
Retry-Afterhint anderror.typeare gone, so a Responses client cannot tell apermanent failure from a transient one. In practice clients retried permanent 403s and could not
back off correctly on 429/503.
Root cause
open-sse/utils/earlyStreamKeepalive.ts, non-SSE branch of the slow path: the handler's errorResponseis read as text and reshaped bybuildResponsesErrorDataLine(text), which only keepscode,message,param(plusdiagnostics). The status and headers of thatResponsearenever looked at.
Fix
The post-commit Responses error frame now also carries:
status_code: the handler response status (always present in this branch).error_type:error.typefrom the body, when present.retry_after_seconds:Retry-After(delta-seconds or HTTP-date), elsex-omniroute-retry-after-seconds, clamped to0..3600; omitted when neither header is usable.Design notes:
error_type, nottype: top-leveltypeis the Responses event discriminator.errorobject: openai-node throws on an event with a top-levelerrorkey instead of yielding it, which would undo fix(api): frame post-keepalive /v1/responses stream errors with a type field #13431.unchanged. Only additive fields; existing keys keep their values.
Follow-up of #13431; related #14377.
Tests
tests/unit/responses-post-keepalive-error-frame-status.test.ts(red before the fix,green after): 429 with
Retry-Afterdelta-seconds, HTTP-dateRetry-Afterclamped to 3600,the
x-omniroute-retry-after-secondsfallback, 403 without a retry hint, a body withouterror.type, and unchanged fast path and chat frames.node --import tsx/esm --teston the new test plusissue-13431-responses-post-keepalive-error-frame,early-stream-keepalive,earlyStreamKeepalive,responses-route-early-keepalive-wiring,keepalive-threshold:54 tests, 52 pass, 2 pre-existing skips, 0 fail.
eslint(with the repo suppressions) clean on both files.