Skip to content

fix(providers): retry streaming requests dropped before first body bytes - #10779

Closed
vincenzopalazzo wants to merge 6 commits into
aaif-goose:mainfrom
vincenzopalazzo:fix/stream-retry-mid-stream-network-errors
Closed

fix(providers): retry streaming requests dropped before first body bytes#10779
vincenzopalazzo wants to merge 6 commits into
aaif-goose:mainfrom
vincenzopalazzo:fix/stream-retry-mid-stream-network-errors

Conversation

@vincenzopalazzo

@vincenzopalazzo vincenzopalazzo commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Issue: #10887 (#10926, which @DOsinga opened for this PR, was closed as a duplicate of it and #10887 now carries the agreed plan).

Rebased onto main. cargo test -p goose-providers is green (132 tests), including the new stream_retries_when_connection_drops_before_first_body_bytes. The rebase was not mechanical: main has since extracted stream_payload / stream_responses_payload helpers, so the first-chunk-inside-retry change now lives in those helpers instead of being inlined at each call site.

Note

This PR does not match the plan agreed on #10887, and I would like a steer before reworking it.

The plan there is to add first-item retry in stream_response_from_provider and leave stream-creation retries at the provider level. This PR instead stays entirely at the provider level: it pulls the first body chunk inside the provider's existing with_retry scope, so a connection that dies before delivering any bytes is retried as a failed request rather than surfacing as a mid-stream item error where retry is unreachable.

I think these are complementary rather than competing — this one closes the window between "headers arrived" and "first byte arrived", which is below the level stream_response_from_provider can see, while the agreed plan covers a transient first item after a well-formed stream opens. But if the intent is for the agent-level handling to subsume this case, say so and I will close this in favour of an implementation of the #10887 plan.


Summary

  • Mid-stream network failures (error decoding response body) bypassed goose's provider retry entirely: with_retry wrapped only the HTTP request and handle_status(resp), so the retry scope ended the moment response headers arrived. A cut SSE connection surfaced as a per-item Err(NetworkError) inside the body stream, long after any retry scope, and the agent's reply loop aborted the whole turn on the first stream error.
  • Root cause: should_retry(NetworkError) = true was dead code for the one network error that actually occurs with SSE providers — it could only fire for pre-headers failures.
  • Fix: await the first body chunk (first_body_chunk) inside the with_retry closure in openai.rs (chat completions + responses API paths) and openai_compatible.rs, then prepend it to the reconstructed body stream (stream_openai_compat_with_prefix / stream_responses_compat_with_prefix). Any failure before the first token — the common case — is now transparently retried with the existing backoff.
  • Scope note: failures after the first token remain non-retryable (transparent resume would duplicate already-yielded partial content); that needs an agent-level turn retry and is left for a follow-up.

Test plan

  • Regression test openai::tests::stream_retries_when_connection_drops_before_first_body_bytes: raw TCP server returns 200 headers with a promised 1024-byte body then drops the connection; retry serves a full SSE response. Verified the test fails without the fix and passes with it.
  • cargo test -p goose-providers (87 passed)
  • cargo clippy -p goose-providers -p goose --all-targets -- -D warnings
  • CI passes

@vincenzopalazzo
vincenzopalazzo force-pushed the fix/stream-retry-mid-stream-network-errors branch from 3cb2cf0 to 200ca24 Compare July 29, 2026 08:06

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 200ca2404f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/goose-providers/src/openai_compatible.rs Outdated
@vincenzopalazzo
vincenzopalazzo force-pushed the fix/stream-retry-mid-stream-network-errors branch from 200ca24 to c0bdfbb Compare July 29, 2026 14:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c9d632a8d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/goose-providers/src/openai_compatible.rs
@DOsinga

DOsinga commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Thank you for the work on this — it addresses a real reliability gap. We've captured the issue as #10926: the HTTP request can successfully establish a stream, ending the existing request retry scope, but reading or decoding that stream can still fail before the first response item reaches the agent.

There are two open approaches to the same problem here and in #10534. Before choosing an implementation, we should agree in #10926 whether the retry boundary belongs around the first raw body chunk or the first parsed provider-stream item, along with replay-safety constraints and a verification plan. I've moved the issue to Accepted / design for that discussion. Per CONTRIBUTING.md, implementation should follow once the issue reaches Ready and the PR should link it. Please bring the design trade-offs and regression-test approach from this PR to the issue; they are useful input to that decision.

@vincenzopalazzo

Copy link
Copy Markdown
Contributor Author

Verification after rebase

  • cargo test -p goose-providers — 132 passed, including stream_retries_when_connection_drops_before_first_body_bytes.
  • cargo clippy -p goose-providers --all-targets -- -D warnings — clean.

The with_retry scope in the OpenAI and OpenAI-compatible providers ended
the moment response headers arrived, so an SSE connection cut before
delivering any body (reqwest's "error decoding response body") surfaced
as a mid-stream item error where retry is structurally unreachable,
aborting the whole turn.

Await the first body chunk inside the with_retry closure and prepend it
to the reconstructed body stream, so pre-first-token failures — the
common case with long-lived SSE connections — are transparently retried
with the existing backoff. should_retry(NetworkError) is no longer dead
code for this failure mode.

Adds a regression test with a raw TCP server that drops the first
connection after 200 headers and serves a full SSE response on retry.
@vincenzopalazzo
vincenzopalazzo force-pushed the fix/stream-retry-mid-stream-network-errors branch from 91e8ed6 to 146a780 Compare August 10, 2026 18:12
Apply the same first-body-chunk-inside-retry pattern to Databricks,
OpenRouter, GitHub Copilot, NanoGPT, Tetrate, and Bedrock mantle so a
200 OK that dies before any body bytes is still retried.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b78310eac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/goose-providers/src/databricks_v2.rs
vincenzopalazzo and others added 2 commits August 10, 2026 20:36
rmcp 3 renamed Meta to MetaObject; update the sanitization test so the
crate builds under --all-targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply first_body_chunk inside with_retry for Databricks v2 Anthropic
messages and the Anthropic provider stream path, using the shared
body_stream_with_prefix helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: def841041f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/goose-providers/src/openai_compatible.rs
Apply first_body_chunk inside with_retry for Google, ChatGPT Codex,
Gemini OAuth, and Kimi Code stream paths using body_stream_with_prefix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vincenzopalazzo
vincenzopalazzo force-pushed the fix/stream-retry-mid-stream-network-errors branch from 3d07798 to a08ce85 Compare August 10, 2026 19:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a08ce855dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/goose-providers/src/openai_compatible.rs
Apply first_body_chunk inside the retry path for Ollama streaming and
GCP Vertex AI send_request_with_retry, replaying via body_stream_with_prefix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@DOsinga

DOsinga commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

closing since #11107 fixes thsis

@DOsinga DOsinga closed this Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants