openai-base: a tool call cut off by finish_reason "length" is reported as "tool_calls" and re-sent
I maintainer di solito rispondono entro 1 giorno
@tombeckenham ci sta già lavorando.
Dal 22/10/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
TanStack AI version
@tanstack/ai 0.71.0, @tanstack/ai-openai 0.31.0 (@tanstack/openai-base 0.16.0)
Framework/Library version
Node.js 22, chat() on the server, no framework
Describe the bug and the steps to reproduce it
With the Chat Completions adapter, when max_tokens runs out in the middle of a tool call's arguments, the stream
ends with finish_reason: "length". chat() then:
- emits
TOOL_CALL_ENDfor the unfinished arguments andRUN_FINISHEDwithfinishReason: "tool_calls", so the
token limit is lost; - treats the arguments as a tool parse failure (
TOOL_CALL_RESULT:Failed to parse tool arguments as JSON) and
sends the conversation back to the model. With the samemax_tokensthe next answer is usually cut off too; in the
repro onechat()call sends 5 requests.
The finish is chosen at
packages/openai-base/src/adapters/chat-completions-text.ts#L1392-L1399:
emittedAnyToolCallEnd wins over the pending length. For plain text the adapter already passes length through.
Expected: finishReason: "length" (the arguments are incomplete because of the limit, not malformed), and no
automatic retry of a call the limit cut off.
Steps: save the script below as repro.mjs, then
npm init -y && npm pkg set type=module
npm install @tanstack/[email protected] @tanstack/[email protected]
node repro.mjs
Output:
RUN_FINISHED tool_calls
TOOL_CALL_RESULT {"error":"Failed to parse tool arguments as JSON: {\"title\":\"Pottery workshop in Mál"}
(the two lines above repeat five times)
requests: 5
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
No API key is needed: a custom fetch returns the stream.
import { chat, toolDefinition } from '@tanstack/ai';
import { createOpenaiChatCompletions } from '@tanstack/ai-openai';
// The arguments stop mid-string because max_tokens ran out; the API says so with finish_reason "length".
const chunk = (delta, finish_reason = null) => ({ id: 'chatcmpl-1', object: 'chat.completion.chunk', created: 1,
model: 'gpt-6-luna', choices: [{ index: 0, delta, finish_reason }] });
const body = [
chunk({ role: 'assistant', tool_calls: [{ index: 0, id: 'call_1', type: 'function',
function: { name: 'create_event', arguments: '{"title":"Pottery workshop in Mál' } }] }),
chunk({}, 'length'),
].map(value => `data: ${JSON.stringify(value)}\n\n`).join('') + 'data: [DONE]\n\n';
let requests = 0;
globalThis.fetch = async () => {
requests += 1;
return new Response(body, { headers: { 'content-type': 'text/event-stream' } });
};
const createEvent = toolDefinition({
name: 'create_event', description: 'Create a calendar event',
inputSchema: { type: 'object', properties: { title: { type: 'string' } }, required: ['title'] },
});
for await (const event of chat({
adapter: createOpenaiChatCompletions('gpt-6-luna', 'test-key'),
messages: [{ role: 'user', content: 'Create an event for a pottery workshop in Málaga.' }],
tools: [createEvent],
modelOptions: { max_tokens: 12 },
debug: false,
})) {
if (event.type === 'RUN_FINISHED') console.log('RUN_FINISHED', event.metadata?.tanstack?.finishReason);
if (event.type === 'TOOL_CALL_RESULT') console.log('TOOL_CALL_RESULT', event.content);
}
console.log('requests:', requests);
Terms & Code of Conduct
- I agree to follow this project's Code of Conduct
- I understand that if my bug cannot be reliably reproduced in a debuggable environment, it will probably not be
fixed and this issue may even be closed.
- Lingua principale
- TypeScript
- Stelle
- 3.2k
- Fork
- 365
- Merge medio
- 1g 9h
- PR unite (30g)
- 263
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di TanStack/ai
-
ai-ollama: streamed chat() reports finishReason "stop" when done_reason is "length"Forse già presa @AlemTuzlak l’ha presa 1 giorno fa. Apertawaiting-on: maintainer
TanStack/ai#1852 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
ai-vercel-gateway: surface provider_metadata.gateway cost on usage (usage.cost)Forse già presa @tombeckenham l’ha presa 1 giorno fa. Apertawaiting-on: maintainer
TanStack/ai#1845 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
withPersistence does not save activity rows when a run is stopped or failsForse già presa @tombeckenham l’ha presa 6 giorni fa. Apertawaiting-on: maintainer
TanStack/ai#1804 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Discriminate status-dependent record and option types (RunRecord, SessionIndexEntry, InputState, durable-only options)Forse già presa @jherr l’ha presa 7 giorni fa. Apertaenhancement waiting-on: maintainer
TanStack/ai#1799 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
ai-harness: an input with no principal runs with the owner session's principalForse già presa @tombeckenham l’ha presa 7 giorni fa. Apertawaiting-on: maintainer
TanStack/ai#1797 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Issue simili
-
数据界面的横向滚动条缺失Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
zilliztech/attu#1037 ·
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
openclaw/openclaw#181212 · 1 commento · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
apify/apify-mcp-server#1684 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
Automattic/data-liberation-agent#953 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
siteboon/claudecodeui#1642 ·
I maintainer di solito rispondono entro 5 giorni