Skip to content

@ai-sdk/open-responses: truncated stream emits reasoning-end with a hardcoded id, and unknown incomplete reasons are reported as tool-calls #18872

Closed

Description

@Astro-Han

Two defects in the streaming path, both in @ai-sdk/open-responses@2.0.27. They are filed together because both surface on the same trace: a response that ends early while reasoning is open.

1. reasoning-end id does not match reasoning-start

Start and end use the real item id:

// dist/index.js — response.output_item.added / .done
controller.enqueue({ type: "reasoning-start", id: chunk.item.id });
controller.enqueue({ type: "reasoning-end",   id: chunk.item.id });

but the flush path, which runs when the stream ends while reasoning is still open, hardcodes an id:

// dist/index.js:703
flush(controller) {
  if (isActiveReasoning) {
    controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
  }

With a real id such as rs_…, AI SDK core then injects error: reasoning part reasoning-0 not found. A truncated-but-otherwise-usable response is delivered to the caller as a stream error rather than a normal length finish. chunk.item.id is not in scope at flush time, so the fix is to remember the active reasoning id when reasoning-start is emitted and reuse it here.

2. An unrecognized incomplete_details.reason becomes tool-calls

// dist/index.js:267-282
switch (finishReason) {
  case void 0: case null:      return hasToolCalls ? "tool-calls" : "stop";
  case "max_output_tokens":    return "length";
  case "content_filter":       return "content-filter";
  default:                     return hasToolCalls ? "tool-calls" : "other";
}

max_output_tokens and content_filter are handled correctly. Any other reason an OpenAI-compatible server reports falls to default, and when tool calls are present the truncation is reported as tool-calls — indistinguishable from a healthy tool round. An agent loop reads that as "the model wants to call a tool", continues, and never learns the response was cut short. The real reason survives on finishReason.raw, but unified is what control flow reads.

other for an unknown reason would be conservative and correct; hasToolCalls should not upgrade an unknown terminal state to a successful one.

Version

@ai-sdk/open-responses@2.0.27

Activity

  1. ai-sdk-factory commented on Aug 13, 2026

    @ai-sdk-factory
    Contributor

    Identify issue type

    Identified as Bug
    Confidence: High

    Rationale

    This is a concrete report of two incorrect behaviors in the existing streaming implementation: mismatched reasoning IDs produce an unexpected stream error, and unknown incomplete reasons receive a misleading finish classification.

    Evidence

    • The flush path emits reasoning-end with hardcoded id reasoning-0, which can mismatch the actual reasoning-start id and trigger reasoning part reasoning-0 not found.
    • Unknown incomplete_details.reason values are mapped to tool-calls when tool calls exist, causing a truncated response to be treated as a healthy tool-call round.
    • The report identifies both failures in the current streaming behavior of @ai-sdk/open-responses@2.0.27 and provides relevant implementation paths.
  2. ai-sdk-factory commented on Aug 13, 2026

    @ai-sdk-factory
    Contributor

    Bug Reproduction - AI SDK 7

    Bug was reproduced.

    Branch: main
    PR: successful reproduction pull request

    Details

    • examples/ai-functions/src/reproduction/open-responses-truncated-reasoning.ts reproduces both defects against the checked-out @ai-sdk/open-responses@2.0.27 implementation.
    • With packages/open-responses/src/responses/__fixtures__/issue-18872-truncated-reasoning.chunks.txt, truncation while reasoning ID rs_actual_reasoning_id is open produces reasoning part reasoning-0 not found; the expected outcome is an error-free stream with finish reason length.
    • With packages/open-responses/src/responses/__fixtures__/issue-18872-unknown-incomplete-reason.chunks.txt, unknown reason server_timeout with a tool call is reported as tool-calls; the expected conservative unified reason is other while preserving the raw reason.
    • Regression assertions added to packages/open-responses/src/responses/open-responses-language-model.test.ts fail on the hardcoded reasoning-end ID and incorrect unknown-reason mapping.

    Relevant Documentation

  3. self-assigned this
    on Aug 13, 2026
  4. added a commit that references this issue on Aug 13, 2026
    07f969a
  5. ai-sdk-factory commented on Aug 13, 2026

    @ai-sdk-factory
    Contributor

    Bugfix - AI SDK 7

    Created bugfix and opened PR: #18881

    Root Cause

    The stream flush path retained only a reasoning-active boolean and hardcoded reasoning-0 instead of retaining the active item ID. Separately, the finish-reason mapper allowed hasToolCalls to override unknown terminal reasons. The recorded reproduction confirmed both outcomes.

    Summary

    The stream now retains and reuses the active reasoning ID during flush, while unknown incomplete reasons map conservatively to other. Added a patch changeset for @ai-sdk/open-responses.

    Testing

    Added stream regressions for truncated reasoning IDs and unknown incomplete reasons with tool calls, and updated finish-reason mapping coverage.

  6. n1ckoates commented on Aug 13, 2026

    @n1ckoates
    Member
    • First bug sounds like a real bug to me
    • Second bug seems intended
  7. github-actions commented on Aug 14, 2026

    @github-actions
    Contributor

    🚀 Published in:

    Package Version
    ai 7.0.66 github npm
    @ai-sdk/amazon-bedrock 5.0.56 github npm
    @ai-sdk/angular 3.0.66 github npm
    @ai-sdk/anthropic 4.0.39 github npm
    @ai-sdk/anthropic-aws 2.0.31 github npm
    @ai-sdk/code-mode 1.0.23 github npm
    @ai-sdk/google-vertex 5.0.54 github npm
    @ai-sdk/harness 1.0.72 github npm
    @ai-sdk/harness-acp 1.0.9 github npm
    @ai-sdk/harness-claude-code 1.0.75 github npm
    @ai-sdk/harness-cline 1.0.0 github npm
    @ai-sdk/harness-codex 1.0.74 github npm
    @ai-sdk/harness-deepagents 1.0.72 github npm
    @ai-sdk/harness-grok-build 1.0.8 github npm
    @ai-sdk/harness-opencode 1.0.73 github npm
    @ai-sdk/harness-pi 1.0.73 github npm
    @ai-sdk/langchain 3.0.66 github npm
    @ai-sdk/llamaindex 3.0.66 github npm
    @ai-sdk/mcp 2.0.32 github npm
    @ai-sdk/minimax 3.0.15 github npm
    @ai-sdk/open-responses 2.0.28 github npm
    @ai-sdk/otel 1.0.66 github npm
    @ai-sdk/policy-opa 1.0.66 github npm
    @ai-sdk/react 4.0.69 github npm
    @ai-sdk/rsc 3.0.66 github npm
    @ai-sdk/sandbox-just-bash 1.0.72 github npm
    @ai-sdk/sandbox-vercel 1.0.72 github npm
    @ai-sdk/svelte 5.0.66 github npm
    @ai-sdk/tui 1.0.67 github npm
    @ai-sdk/vue 4.0.66 github npm
    @ai-sdk/workflow 1.0.66 github npm
    @ai-sdk/workflow-harness 1.0.72 github npm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions