Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

openai-base: a Responses max_output_tokens cutoff ends as RUN_ERROR without usage instead of finishReason 'length'

Abierto Apto para principiantes
#1,916 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@pcbeingused333 ya está trabajando en esto.

Desde el 28/10/2026.

  • #1929 de @pcbeingused333 — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
74/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
typescript

Línea de trabajo

Empieza en packages/openai-base/src/adapters/responses-text.ts y compara el manejo de response.incomplete cerca de las líneas 1748–1806 con la asignación de response.completed cerca de las líneas 2442–2473. Revisa las pruebas del adaptador para los eventos terminales, usage y finish reasons. El trabajo estará terminado cuando los motivos de respuesta incompleta conocidos finalicen con usage y el motivo asignado, mientras que las respuestas fallidas o con un motivo desconocido sigan siendo errores.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

What happens

When a Responses stream hits max_output_tokens, it ends with response.incomplete (status: "incomplete", incomplete_details.reason: "max_output_tokens"), and that event carries the response's usage. The Responses adapter in @tanstack/openai-base turns it into RUN_ERROR (message: "max_output_tokens", code: "incomplete") and drops the usage:

https://github.com/TanStack/ai/blob/ae976552710726b13b524c307c1b5bbe78478eb0/packages/openai-base/src/adapters/responses-text.ts#L1748-L1806

So with the Responses adapter:

  • the run ends in onError, not onFinish, right after the partial text the user has already seen;
  • onUsage never fires, although the provider billed the tokens;
  • finishReason: 'length' never appears, so untilFinishReason(['length']) and the core stop-on-length path (#1874) never see a capped answer.

The response.completed branch already maps incomplete_details.reason (max_output_tokens → length, content_filter → content_filter), "mirroring the chat-completions adapter". A capped response does not arrive as response.completed, so that mapping is not reached for it:

https://github.com/TanStack/ai/blob/ae976552710726b13b524c307c1b5bbe78478eb0/packages/openai-base/src/adapters/responses-text.ts#L2442-L2473

The Chat Completions adapter reports the same cutoff as RUN_FINISHED with usage and finishReason: 'length'.

Repro

@tanstack/ai 1.0.0, @tanstack/openai-base 1.0.0, @tanstack/ai-vercel-gateway 1.0.0, server-side chat() on Node 24

for await (const chunk of chat({
  adapter: createVercelGatewayText('openai/gpt-4.1-nano', key), // Responses API by default
  messages: [{ role: 'user', content: 'Count from 1 to 300, separated by commas.' }],
  threadId: 'repro',
  modelOptions: { max_output_tokens: 16 },
  middleware: [{ name: 'probe', onUsage, onFinish, onError }],
})) {
  if (chunk.type === 'RUN_FINISHED' || chunk.type === 'RUN_ERROR') console.log(chunk)
}
Adapter Terminal chunk onUsage Terminal hook
Responses (default) RUN_ERROR { message: 'max_output_tokens', code: 'incomplete' } not called onError
Chat Completions (api: 'chat', max_tokens: 16) RUN_FINISHED, usage 19 / 16 called once onFinish, finishReason: 'length'

On the Responses adapter the chunks arrive as RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT (62 characters), TEXT_MESSAGE_END, RUN_ERROR. anthropic/claude-sonnet-5.5 gives the same RUN_ERROR. A direct POST https://ai-gateway.vercel.sh/v1/responses with stream: true and max_output_tokens: 16 ends like this for both models (gpt-4.1-nano shown):

{
  "type": "response.incomplete",
  "response": {
    "status": "incomplete",
    "incomplete_details": { "reason": "max_output_tokens" },
    "usage": { "input_tokens": 19, "output_tokens": 16, "…": "…" }
  }
}

The openai SDK types describe response.incomplete as "An event that is emitted when a response finishes as incomplete", with incomplete_details.reason one of max_output_tokens, max_messages, content_filter, steered.

Expected

response.incomplete with incomplete_details.reason max_output_tokens or content_filter ends the run the way the Chat Completions adapter does: RUN_FINISHED with the response's usage and finishReason: 'length' or 'content_filter'. response.failed, and an incomplete response without a known reason, stay RUN_ERROR.

Why

We stop our agent loop with untilFinishReason(['length']) and record usage per model call. On the Responses adapter, a capped answer shows the user an error after a partial answer, and its tokens are not recorded.

Lenguaje dominante
TypeScript
Estrellas
3.2k
Forks
372
Merge medio
1 d 14 h
PR fusionados (30 d)
241

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de TanStack/ai

Todos los issues de TanStack/ai

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.