Skip to content

Instantly share code, notes, and snippets.

@donpark
Created September 15, 2026 18:26
Show Gist options
  • Select an option

  • Save donpark/8a502f227849b19538d0db3499e1b5fd to your computer and use it in GitHub Desktop.

Select an option

Save donpark/8a502f227849b19538d0db3499e1b5fd to your computer and use it in GitHub Desktop.
vercel-ai-gateway / deepseek-v4.1-flash: runaway tool-tag repetition loop in reasoning channel (pi 0.85.1)

Gateway/provider glitch: runaway tool-tag repetition loop in reasoning channel

Summary

Via vercel-ai-gateway serving deepseek/deepseek-v4.1-flash with thinking level high, the model sporadically enters a decoding loop while emitting tool-call markup inside the reasoning/thinking channel. After writing a normal <parameter>…</parameter> block it never closes the call, and instead emits a constant 23-byte cycle forever:

</parameter>\n</invoke>\n</parameter>\n</invoke>\n …  (1091 repeats observed)

The same model id served by openrouter produced zero such output in the same sessions.

  • Host: pi coding agent 0.85.1
  • Project: /Users/don/dev/idfon
  • Provider: vercel-ai-gateway
  • Model id: deepseek/deepseek-v4.1-flash
  • Thinking level: high
  • Window: 2026-09-14 02:45:15Z … 2026-09-14 21:24:23Z (UTC)
  • 11 affected assistant messages, ~5,932 tag-loop iterations total
  • 1 instance leaked into user-visible output (not just reasoning)

Pattern details

Two variants, both exact fixed-stride loops:

variant cycle stride seen in
A (dominant) </parameter>\n</invoke>\n 23 chars, 1091 consecutive cycles msgs below
B </invoke>\n</function_calls>\n 28 chars 8a0c4880

Trigger context (consistent): the model is reasoning about which command to run and starts writing a tool call inline in the thinking text, e.g.

Let me read both — this is decisive.

<parameter name="command">cd /tmp && curl -sSL ... | head -c 5500</parameter>
</invoke>
</parameter>
</invoke>
… loop …

Variant B is self-aware and still fails — the model writes I need to stop generating malformed markup. Here is the intended tool call, correctly formed: and then emits Anthropic-namespace markup <antml:invoke name="bash">…. <antml: appears once in this log and once in the 2026-09-13 log (possible tool-format/backend mismatch clue).

Evidence table

timestamp (UTC) message id channel loop iters output tok stopReason responseId
2026-09-14T02:45:15.250Z 68b6cfe1 thinking 65 3111 toolUse gen_01M2EWVKF92Q1FPXWZDJFAEPP7
2026-09-14T03:56:12.737Z 8310cf45 thinking 1092 8309 toolUse gen_01M2F0VZRCTZ13C74FNWRG9GMR
2026-09-14T03:56:58.337Z 26b3350d thinking 102 4465 stop gen_01M2F0XV2QDJVWKTVECD1XQTJ7
2026-09-14T04:22:27.405Z e403d264 thinking 224 0 aborted gen_01M2F2CW1QNH36RYNNF31M8TJ8
2026-09-14T04:37:47.802Z d51071a2 text (visible) 220 3585 stop gen_01M2F38PYTQMADT2JQQAW60CZ2
2026-09-14T04:44:40.972Z 1ccb4fd9 thinking 53 560 toolUse gen_01M2F3NK5RXVXWSBRATQVCDD0K
2026-09-14T04:47:51.007Z dc432177 thinking 89 0 aborted gen_01M2F3V75SX1CSHACFYZXRS3HB
2026-09-14T04:55:30.937Z e514ee4b thinking 126 0 aborted gen_01M2F49M9P009J693H5NRBYD36
2026-09-14T05:03:21.007Z f91a0761 thinking 210 0 aborted gen_01M2F4R4KTJRY5Z3HWTD9K937T
2026-09-14T05:30:40.019Z 1013b78a thinking 243 0 aborted gen_01M2F69QNA2A2H4Z1SMBEPXJQH
2026-09-14T21:24:23.207Z 8a0c4880 thinking 654 (variant B) 0 aborted gen_01M2GWVWT9JJQBJFTRK55PMQYV

Provider correlation (same model id)

Sessions contain an in-session provider switch from openrouter → vercel-ai-gateway for the same deepseek/deepseek-v4.1-flash id.

  • 2026-09-14 log, switch at 2026-09-14T02:37:57.527Z; first loop at 02:45:15.250Z.
  • The 8 assistant messages on openrouter in that log (02:36:19Z–02:36:58Z) are clean: 0 occurrences of </invoke>, </parameter>, </function_calls>.
  • All 11 loop messages are vercel-ai-gateway. Across the three affected logs, provider counts are: vercel-ai-gateway ×370 assistant msgs (glitches only here) vs openrouter ×8 clean.
  • Caveat: the OpenRouter sample is small (~40 s of an early session), so this is a strong correlation, not proof.

Raw excerpts

8310cf45 (thinking, 1092-iteration variant A):

… channels/custom.md ##########" && curl -sSL --max-time 20 "https://eve.dev/docs/channels/custom.md" | head -c 5500</parameter>
</invoke>
</parameter>
</invoke>
</parameter>
</invoke>
… (1091 repeats) …
</parameterI have to give the solution based on the reasoning directly now.

Note the final malformed merge: </parameterI have to… — the loop is cut off mid-tag by the model/token limit.

d51071a2 (user-visible text, 220 iterations):

Let me read a bit more of the Sessions section to get the exact session API (create, send, result).

<parameter name="command">cd /tmp && sed -n '120,178p' client.md</parameter>
</invoke>
</parameter>
</invoke>
</parameter>
</invoke>
… (219 repeats) …

8a0c4880 (variant B):

… echo "=== unstaged ==="; git status --short | grep -v "^M "</parameter>
</invoke>
</function_calls>
</invoke> understood

I need to stop generating malformed markup. Here is the intended tool call, correctly formed:

<antml:invoke name="bash">
<antml:parameter name="command">cd /Users/don/dev/idfon && git add docs/audio-media.md …

Log locations

  • /Users/don/.pi/agent/sessions/--Users-don-dev-idfon--/2026-09-14T02-20-57-201Z_01a09db7-b3f0-76c0-89ce-d88de2c6df74.jsonl (9 of 11)
  • /Users/don/.pi/agent/sessions/--Users-don-dev-idfon--/2026-09-14T19-41-18-878Z_01a0a170-2e9e-71f2-9b64-7295c9386347.jsonl (variant B)
  • /Users/don/.pi/agent/sessions/--Users-don-dev-idfon--/2026-09-13T21-37-08-072Z_01a09cb3-dbe8-73bd-af78-a5efe4636c8c.jsonl (lead-up, single stray tags)

Suggested minimal repro

Send a multi-turn, tool-using request at thinking level high via vercel-ai-gateway / deepseek/deepseek-v4.1-flash, where the model must reason across several commands (e.g. "fetch these two docs, read them, then decide X"). Look for the reasoning channel containing </parameter>\n</invoke>\n repeated. Compare the same conversation against openrouter with the identical model id.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment