[BUG] Reasoning Loop on Trivial Task

#47
by voves - opened

GLM-5.3-Flash Reasoning Loop: 813K Input Tokens, 0 Lines of Code

TL;DR: GLM-5.3-Flash (via opencode, build mode) got stuck in a reasoning loop on a trivial task — "limit HTTP request size to 1MB" in a Kotlin / Spring Boot + Jetty microservice. The expected fix is a ~15-line OncePerRequestFilter checking Content-Length.

Setup

  • Model: GLM-5.3-Flash
  • Agent: opencode, build mode, v1.18.29
  • Task: "Limit max http request size for this application to 1mb"
  • App: Kotlin / Spring Boot + Jetty microservice, @RequestBody ByteArray endpoints

What the model actually did (~5 min, 20+ tool calls)

  • Explored project structure, read build.gradle.kts, application.yml, controller, service, exception handler, metrics, INFO.md
  • Read the same controller 3 times and the same application.yml 3 times
  • Grepped ~6 sibling projects for existing patterns — none found
  • Loaded a kotlin-backend skill (layered architecture, metrics conventions)
  • Created a 5-item todo list… then kept searching instead of implementing

Loop mechanism (step-by-step)

Step Action Reasoning tokens What happened
1–4 Explore: structure, build files, controller, yml 120–83 Normal discovery phase
5 First long reasoning (359 tok) 359 Model lists 4 options: form-post-size, filter, customizer, RequestBodyAdvice. Decision implicit but not committed.
6 Loads kotlin-backend skill (~500 lines of conventions) 484 Context now contains architecture rules that conflict with "just add a filter"
7–8 Re-reads controller + exception handler (already in context) 482 Model re-analyzes the same code against skill constraints
9–10 Expands search: k8s configs, sibling projects, OncePerRequestFilter grep 615 Seeking external validation of its plan
11 3,772-token reasoning block — most detailed design 3772 Model writes full implementation plan, creates todo list. Should have started coding here.
12–13 Re-reads application.yml again (3rd time), more greps 35 Post-plan, model still searching for "prior art" in 6 sibling projects
14 (ABORTED) ~176 sec pure reasoning, no tool calls Reasoning text is near-verbatim repeat of step 5. Model re-derives the same 4 options. MessageAbortedError.

The loop: After step 5 the model had all information needed to implement. Steps 6–13 added context (skill, INFO.md, k8s, sibling greps) that diluted the implicit decision without adding a new signal. By step 14, the model's "working memory" of its own prior analysis had degraded — it re-generated the same option list from scratch. No stopping condition detected "I already decided 9 steps ago."

Root causes

  1. No early commitment — oscillated between 4 implementation options without picking one after the first analysis pass
  2. Redundant file re-reads — same files fetched 3x, pure token waste (813K input for 1.6K output)
  3. Pattern-seeking overdrive — infinite greps for conventions that don't exist; no pivot to "just implement the standard approach"
  4. Skill instructions added friction — heavy architectural conventions made the model overthink a 20-line filter
  5. No progress gate — no detection of "re-read same file 3x, still in analysis phase"

Result

0 additions, 0 deletions, 0 files changed.

Are you calling the API service through OpenCode? Do you have a script /prompt that can reproduce the issue?

The setup is self-hosted GLM-5.3-Flash on SGLang with DFLash2 by incoai (looping happens with on/off dflash). I can share the whole session.

SGLang setup:

sglang serve
--model-path /models/zai-org/GLM-5.3-Flash
--served-model-name GLM-5.3-Flash
--host 0.0.0.0
--port 8000
--tp-size 4
--ep-size 4
--allow-auto-truncate
--mem-fraction-static 0.85
--chunked-prefill-size 8192
--dsa-prefill-backend trtllm
--dsa-decode-backend trtllm
--speculative-algorithm DFLASH
--speculative-draft-model-path /models/incoai/GLM-5.3-Flash-DFlash2
--speculative-draft-attention-backend fa4
--kv-cache-dtype fp8_e4m3
--moe-runner-backend deep_gemm
--reasoning-parser glm45
--tool-call-parser glm47
--max-running-requests 48
--cuda-graph-max-bs-decode 48
--context-length 200000
--trust-remote-code
--enable-metrics
voves changed discussion status to closed
voves changed discussion status to open

@ZHANGYUXUAN-zR I'm was having the same issue with vLLM (glm53 docker tag).

Reverting the chat template to the original one(the one before the sglang fixed) seems to fixed it.

It was client dependent though, some work fine, some didn't.

This is strange, because the template change is a purely positive fix — it doesn't break anything.

@ZHANGYUXUAN-zR I noticed this when using:

  • Cline VSCode extension.
  • pydantic-ai using the VLLMProvider and OpenAIProvider.

Basically saying just "Hello" would cause the model to loop for 20-30s then go into an infinite loop saying the same thing.

The model would behave normal with Claude, Codex, and Open-WebUI.

@ZHANGYUXUAN-zR the issue is very similar to the one reported here https://huggingface.co/zai-org/GLM-5.3-Flash/discussions/23

But we are not using any weird setup. Downloaded model weights via git-lfs then started vllm pointing to that directory. Same setup as GLM-5.2

I wonder if it is related to this: https://github.com/vllm-project/vllm/issues/54744#issuecomment-5506461377

Fixed this issue forcing clear_thinking to true by default in chat_template.jinja, @ZHANGYUXUAN-zR thank you for support.

{%- set clear_thinking = clear_thinking if clear_thinking is defined else false -%} 

to

{%- set clear_thinking = clear_thinking if clear_thinking is defined else true -%}
voves changed discussion status to closed

@voves thanks for sharing, i will give that a try.

Not fixed using latest vLLM. see https://github.com/vllm-project/vllm/issues/56605

@g-a-b-y , I am using base sglang image(the one mentioned in cookbook) + some patches for dflash2, fyi

voves changed discussion status to open

Sign up or log in to comment