Skip to content

fix(providers): name the failing phase of a stalled OpenAI call, and reject a failed generation - #6283

Merged
waleedlatif1 merged 5 commits into
stagingfrom
fix/openai-provider-transport-diagnostics-v2
Aug 5, 2026
Merged

fix(providers): name the failing phase of a stalled OpenAI call, and reject a failed generation#6283
waleedlatif1 merged 5 commits into
stagingfrom
fix/openai-provider-transport-diagnostics-v2

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • An agent block hung ~4.5 min with an empty trace, surfacing only the runtime's TimeoutError: The operation timed out. Root cause: the model repeated one tool call until it consumed the full 128,000-token output budget. /v1/responses withholds its 200 until generation finishes, so the client waited — bounded only by an undocumented runtime socket deadline — and gave up before the response existed. Confirmed against OpenAI's stored response (status: incomplete, reason: max_output_tokens).
  • Name the phase a transport failure died in — awaiting-response-headers vs reading-response-body — with status, ttfb, content-length and x-request-id. Precedent: undici splits these into UND_ERR_HEADERS_TIMEOUT / UND_ERR_BODY_TIMEOUT; the OpenAI SDK captures x-request-id. It rides the error message because that reaches the trace span, which survives when a task stops shipping logs.
  • Carry the cause through ProviderError so a transport timeout still classifies after wrapping overwrites name.
  • Reject a 200 reporting a failed or unusable generation instead of returning empty content with billed tokens, and stop truncated tool calls executing. Matches streamResponsesTurn (already did this) and @ai-sdk/openai (throws on the same condition).
  • Bound non-JSON error bodies so a gateway error page can't become the block error.

Deliberately excluded: a response-body deadline (the observed failure is in the headers phase; body transfer measured at ~1 ms) and status-based retries (worth doing, unrelated, separable).

Type of Change

  • Bug fix

Testing

Tested manually against the live API plus 14 new unit tests.

  • Root cause confirmed from OpenAI's stored responses for the actual incident — all three turns, the third at exactly 128,000 output tokens.
  • Verified live that /v1/responses withholds its 200 until generation completes (14,545 ms to headers, 1 ms of body), which is why only the headers phase matters here.
  • Replayed real captured /v1/responses payloads (completed, incomplete/max_output_tokens, tool-call) through the provider — none rejected by the new guard.
  • Every new test verified able to fail by breaking the implementation first.
  • Full suite green; boundary audit, typecheck and lint clean.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 5, 2026 6:05am

Request Review

@cursor

cursor Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Summary

Cursor Bugbot is generating a summary for commit 76c8e91. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR improves OpenAI failure diagnostics and rejects unsuccessful or unusable non-streaming generations.

  • Annotates transport timeouts and aborts with the request phase, timing, and available response metadata.
  • Preserves transport causes through ProviderError so agent handling can classify wrapped timeouts.
  • Rejects failed, non-tolerable incomplete, and truncated tool-call responses while retaining usable truncated prose.
  • Bounds unstructured HTTP error bodies and adds focused regression coverage.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains within the scope of this follow-up review.

Important Files Changed

Filename Overview
apps/sim/providers/openai/core.ts Adds transport-phase diagnostics, bounded error parsing, generation-status validation, and cause-preserving provider errors.
apps/sim/providers/types.ts Extends ProviderError to accept standard ErrorOptions and retain wrapped causes.
apps/sim/executor/handlers/agent/agent-handler.ts Classifies timeout and abort failures through the cause chain while preserving provider diagnostics.
apps/sim/providers/openai/core.response-status.test.ts Covers failed and incomplete response handling, truncated tool calls, and continuation turns.
apps/sim/providers/openai/core.transport-phase.test.ts Covers header/body phase annotation, request metadata, bounded error bodies, and fallback behavior.
apps/sim/executor/handlers/agent/agent-handler.test.ts Verifies wrapped timeout and abort classification at the agent-handler boundary.

Sequence Diagram

sequenceDiagram
  participant Agent as Agent Handler
  participant Provider as OpenAI Provider
  participant API as OpenAI Responses API
  Agent->>Provider: Execute model request
  Provider->>API: Fetch response
  alt Transport failure
    API--xProvider: Timeout or abort
    Provider->>Provider: Attach phase and response metadata
    Provider--xAgent: ProviderError with preserved cause
    Agent->>Agent: Classify cause-chain timeout
  else HTTP 200 response
    API-->>Provider: Response payload
    Provider->>Provider: Validate generation status
    alt Failed or unusable generation
      Provider--xAgent: Reject generation
    else Completed or usable truncated prose
      Provider-->>Agent: Return provider response
    end
  end
Loading

Reviews (4): Last reviewed commit: "fix(providers): name the body phase when..." | Re-trigger Greptile

…reject a failed generation

An agent block hung ~4.5 minutes with an empty trace and surfaced only the
runtime's own `TimeoutError: The operation timed out.` The cause was a runaway
generation: the model repeated one tool call until it consumed the whole
128,000-token output budget, which takes minutes, and `/v1/responses` withholds
its 200 until generation finishes — so the client waited, bounded only by an
undocumented runtime socket deadline, and gave up before the response existed.

Nothing in the trace could distinguish that from a request the provider never
answered, or from one whose body never arrived.

- Name the phase a transport failure died in — `awaiting-response-headers` vs
  `reading-response-body` — with status, ttfb, content-length and
  `x-request-id`. undici draws the same line as two error types
  (UND_ERR_HEADERS_TIMEOUT / UND_ERR_BODY_TIMEOUT); the OpenAI SDK captures
  `x-request-id` for the same reason. It rides the error message because that
  reaches the trace span, which survives when a task stops shipping logs.
- Carry the cause through `ProviderError` so a transport timeout still
  classifies after wrapping overwrites `name`.
- Reject a 200 that reports a failed or unusable generation instead of
  returning empty content with billed tokens, and stop truncated tool calls
  from executing. Matches `streamResponsesTurn`, which already did this, and
  `@ai-sdk/openai`, which throws on the same condition.
- Bound non-JSON error bodies so a gateway error page cannot become the
  user-facing block error.

Deliberately not included: a response-body deadline (the observed failure is in
the headers phase, and the body transfers in ~1ms) and status-based retries
(worth doing, unrelated to this, and separable).
@waleedlatif1
waleedlatif1 force-pushed the fix/openai-provider-transport-diagnostics-v2 branch from bdeea33 to d0dce45 Compare August 5, 2026 05:46
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/providers/openai/core.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/providers/openai/core.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 678384b. Configure here.

@waleedlatif1
waleedlatif1 merged commit 623003e into staging Aug 5, 2026
30 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/openai-provider-transport-diagnostics-v2 branch August 5, 2026 06:17
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.

1 participant