You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Under certain circumstances grok-code (grok code fast 1) rarely gets stuck in a thinking loop.
However I am not sure if this is something OC could completely prevent / detect reliably.
So-called doom-loops do exist in many models, maaaybe excluding Claude/GPT models (correct me if I'm wrong). I saw this happening with Gemini 2.5 flash(severely), grok-code-fast-1, kimi-k2, GLM-4.6 across different agentic coding tools. Including but not limited to: Roo code, opencode.
Radically simplified examples:
Stuck logically
# thinking
- I should check A. let's try that.
- Wait, maybe I did B? That is more important.
- But I should check A first.
- To do that I need to make sure I did B right.
(and so on and on)
Ever increasing tool calls
I need to find A's implementation. let's do that.
tool-call: read-file A.ts offset=1
let's increase that
tool-call: read-file A.ts offset=1, count=10
let's increase that
tool-call: read-file A.ts offset=1, count=20
let's increase that
tool-call: read-file A.ts offset=1, count=#0
let's increase that
...
Ping-pong tool calls
tool-call: Edit A to B
Oh i broke something lets fix that
tool-call: Edit B to A
Now again.
tool-call: Edit A to B
Oh i broke something lets fix that
Let's implement it again.
tool-call: Edit A to B
I made a mistake. reverting.
...
I can see mentions of doom_loop in other completed issues and in codebase, I also found the docs for it, but either it's still unclear to me how it works, or it doesn't work.
I asked a local model to
Run four sequential instances of Bash tool, each doing the same "ls ../questionable"
which doesn't exist and fails.
I verified in the local server logs that all the arriving tool calls are exactly the same, 12 tool calls in total (tried multiple times) and no doom loop prevention. Does the tool call itself have to fail, somehow, instead of the actual command running and resulting in a failure exit code?
but yeah explicit loop detection just seems like the most straight forward solution to a real problem I've experienced.
I'm not sure I agree... 🤔
once you detect a loop, how do you even mitigate? abort the request, correct it somehow, and then restart? this doesn't sound straight forward to me.
and doesn't practically every model have a "repetition penalty" value you can configure?
wouldn't it make more sense to give us better, more visible model controls? e.g. not floating around in a schemaless area of a JSON blob, no idea what's being picked up or if it's being sent to the provider.
personally, I would invest in something that hardens and surfaces this invisible configuration pipeline, and gives us better control. half the time, I'm not sure if putting anything in that JSON file does anything at all.
in my opinion, we need end-to-end validation, and configuration we can safely edit - actual UI that surfaces the available options.
then we'll be able to turn the knobs provided by the models and experiment - I think we should at least try to address the issue at the root of it, before we start coming up with complex half measures. 🤔
Repetition penalties are configured on the LLM provider side, for instance llama.cpp has a few repetition penalty params - AFAICT these repetition penalties are for WITHIN a single output prompt, not for across prompts (which is the type of looping which occurs in an agentic system), so that's not going to help in it's current state. (although maybe a similar system could be adapted using penalties on structured outputs)
AFAICT these repetition penalties are for WITHIN a single output prompt, not for across prompts
it's going to be implementation specific, of course, but afaik the common approach is a sliding context window over the raw context stream... if they restart the window at every turn, it wouldn't prevent repetition across turns... I guess personally I'd consider this "a bug". 🤔
of course, the simpler explanation would be the model hasn't been trained properly, e.g. (in the tool loop case) doesn't recognize failure signals and gets stuck in a "probability well" where the next most likely step is to keep trying. 🤷♂️
either way, it probably makes more sense to wait for an updated, improved model, doesn't it? it's not really the job of the agent to "fix" a broken model or a buggy inference engine, is it? (genuinely asking. not sure.)
Waiting for better models is a valid approach in the current climate, however I suspect the looping will only be reduced not eliminated entirely. For long-running agentic orchestrators if looping happens once in a blue moon then just having a timeout on an opencode session seems fine, however if it happens with a bit more frequency then it would waste lots of time/resources and loop detection / remedy would be useful and worth implementing. In general, generating workarounds for common issues when working with LLMs does seem in scope iff those issues are common enough and exist across providers.
I am curious about repetition penalty based on the context you feed into an agent - I don't think this currently happens, and repetition penalties are only on the llm's output, when you feed in context from an agentic session, naturally the llm has no way of determining what was ITS previous input or what is part of a prompt etc. it's all just mixed together. Again I think there is a possible solution there through either using structured outputs or an entirely new mechanism for repetition penalties... also complex though lol.
I wonder, if a small 1B llm can be used as repetition detector. Just feed in chunks from the main model's output and ask for detection rating. Could even run as a parallel process.
Cool! The basis of the problem I was actually experiencing is (Qwen3-Coder-Next) would just read a file with a small limit (like 30) over and over and over. My workaround was to just fork opencode and ignore the read limit option if it was provided while not also providing an offset.. worked great
I investigated the loop mechanism in the current codebase and found three contributing factors:
1. MAX_STEPS is a soft limit (prompt.ts:1516)
When step >= agent.steps, a text message is injected asking the model to stop using tools, but tools are still passed to the provider. Claude models respect this; non-Claude models (MiniMax, Kimi K2, GLM) often ignore it and keep calling tools.
A hard fix would be passing an empty tools object on isLastStep:
tools: isLastStep ? {} : tools,
This would physically prevent tool calls after the step limit regardless of model.
2. Doom loop detection requires user interaction (processor.ts:187-212)
The doom loop detector (threshold=3 identical calls) triggers a permission.ask() with doom_loop permission. The default is "ask", but when the user's config has "permission": "allow" (common for headless/automated use), this auto-approves and the loop continues indefinitely.
3. Default step limit is Infinity (prompt.ts:1429) agent.steps ?? Infinity means agents without an explicit step limit can loop forever. A sensible default (e.g., 25 or 50) would bound worst-case behavior.
I'd like to work on a fix but wanted to confirm the approach first. The minimal change would be (1) — making MAX_STEPS actually disable tools. Would that be acceptable, or do the maintainers prefer keeping it as a soft prompt for Claude compatibility?
For the “same tool/read call over and over” flavor of this, I published a small OpenCode plugin workaround after reproducing it with Gemini: https://github.com/isac322/opencode-gemini-dejavu / npm: opencode-gemini-dejavu
It is intentionally narrow: it breaks repeated tool-call tails by adding a request-local user boundary and pruning stale prior thought signatures, while preserving the current turn signature.
I hit what appears to be the same repeated-tool-call loop with subagent that uses GLM-5.2
During a code review, the agent repeatedly issued the same two Read calls without progressing to the requested section:
Let me check findByPublicIds SQL scoping and the files.service.spec.ts temp upload test context.
→Read idb_back_2.0/src/files/repositories/media.repository.ts [limit=50]
→Read idb_back_2.0/src/files/services/files.service.spec.ts [limit=100]
→Read idb_back_2.0/src/files/repositories/media.repository.ts [limit=50]
→Read idb_back_2.0/src/files/services/files.service.spec.ts [limit=100]
Thought: 825ms
Let me read the findByPublicIds method at line 1076 to understand SQL scoping.
→Read idb_back_2.0/src/files/repositories/media.repository.ts [limit=50]
→Read idb_back_2.0/src/files/services/files.service.spec.ts [limit=100]
→Read idb_back_2.0/src/files/repositories/media.repository.ts [limit=50]
→Read idb_back_2.0/src/files/services/files.service.spec.ts [limit=100]
→Read idb_back_2.0/src/files/repositories/media.repository.ts [limit=50]
→Read idb_back_2.0/src/files/services/files.service.spec.ts [limit=100]
...
It was trying to inspect a method around line 1076 in media.repository.ts, but repeatedly requested only the initial range and never advanced with an offset. The identical pair repeated dozens of times until the run was cancelled/exhausted.
This had a direct quota impact:
I had just applied a Reward that restored roughly 17% of my weekly limit of opencode-go.
This loop consumed it entirely; the weekly limit is now exhausted again.
It also consumed roughly 8-10% of my monthly limit.
Environment:
macOS
OpenCode CLI
Subagent workflow
Large TypeScript repository
The loop occurred while reviewing a narrow, explicitly scoped diff
Activity
github-actions commentedon Nov 2, 2025
This issue might be a duplicate of existing issues. Please check:
Feel free to ignore if none of these address your specific case.
zenyr commentedon Nov 2, 2025
Under certain circumstances grok-code (grok code fast 1) rarely gets stuck in a thinking loop.
However I am not sure if this is something OC could completely prevent / detect reliably.
So-called
doom-loopsdo exist in many models, maaaybe excluding Claude/GPT models (correct me if I'm wrong). I saw this happening with Gemini 2.5 flash(severely), grok-code-fast-1, kimi-k2, GLM-4.6 across different agentic coding tools. Including but not limited to:Roo code,opencode.Radically simplified examples:
rekram1-node commentedon Nov 2, 2025
We did add some loop detection but as @zenyr points out, there are still some circumstances that it won't quite work
Nindaleth commentedon Dec 16, 2025
I can see mentions of doom_loop in other completed issues and in codebase, I also found the docs for it, but either it's still unclear to me how it works, or it doesn't work.
I asked a local model to
I verified in the local server logs that all the arriving tool calls are exactly the same, 12 tool calls in total (tried multiple times) and no doom loop prevention. Does the tool call itself have to fail, somehow, instead of the actual command running and resulting in a failure exit code?
rekram1-node commentedon Dec 16, 2025
can u share the session?
opencode export > session.jsonNindaleth commentedon Dec 16, 2025
Sure, here's a clean session with the same result (running just the 4 tool calls in this case): session.json
betolink commentedon Dec 23, 2025
Same with GLM 4.7 and opencode
1.0.142palekiwi commentedon Jan 12, 2026
google/gemini-3-pro-previewfrequently ends up in a loop such as:gcc-master commentedon Jan 12, 2026
Same situation with GLM 4.7 on cerebras.ai
session.json
Running session from cli "run" like that
7 remaining items
mindplay-dk commentedon Mar 18, 2026
I'm not sure I agree... 🤔
once you detect a loop, how do you even mitigate? abort the request, correct it somehow, and then restart? this doesn't sound straight forward to me.
and doesn't practically every model have a "repetition penalty" value you can configure?
wouldn't it make more sense to give us better, more visible model controls? e.g. not floating around in a schemaless area of a JSON blob, no idea what's being picked up or if it's being sent to the provider.
personally, I would invest in something that hardens and surfaces this invisible configuration pipeline, and gives us better control. half the time, I'm not sure if putting anything in that JSON file does anything at all.
in my opinion, we need end-to-end validation, and configuration we can safely edit - actual UI that surfaces the available options.
then we'll be able to turn the knobs provided by the models and experiment - I think we should at least try to address the issue at the root of it, before we start coming up with complex half measures. 🤔
bogzbonny commentedon Mar 18, 2026
Repetition penalties are configured on the LLM provider side, for instance llama.cpp has a few repetition penalty params - AFAICT these repetition penalties are for WITHIN a single output prompt, not for across prompts (which is the type of looping which occurs in an agentic system), so that's not going to help in it's current state. (although maybe a similar system could be adapted using penalties on structured outputs)
mindplay-dk commentedon Mar 19, 2026
it's going to be implementation specific, of course, but afaik the common approach is a sliding context window over the raw context stream... if they restart the window at every turn, it wouldn't prevent repetition across turns... I guess personally I'd consider this "a bug". 🤔
of course, the simpler explanation would be the model hasn't been trained properly, e.g. (in the tool loop case) doesn't recognize failure signals and gets stuck in a "probability well" where the next most likely step is to keep trying. 🤷♂️
either way, it probably makes more sense to wait for an updated, improved model, doesn't it? it's not really the job of the agent to "fix" a broken model or a buggy inference engine, is it? (genuinely asking. not sure.)
mindplay-dk commentedon Mar 19, 2026
all that said though, it looks like we wouldn't be the first to handle this at the agent level.
https://www.reddit.com/r/LangChain/comments/1r2mdz1/detecting_infinite_loops_in_langgraph_multiagent/
https://rajatpandit.com/optimizing-langgraph-cycles/
bogzbonny commentedon Mar 19, 2026
Waiting for better models is a valid approach in the current climate, however I suspect the looping will only be reduced not eliminated entirely. For long-running agentic orchestrators if looping happens once in a blue moon then just having a timeout on an opencode session seems fine, however if it happens with a bit more frequency then it would waste lots of time/resources and loop detection / remedy would be useful and worth implementing. In general, generating workarounds for common issues when working with LLMs does seem in scope iff those issues are common enough and exist across providers.
I am curious about repetition penalty based on the context you feed into an agent - I don't think this currently happens, and repetition penalties are only on the llm's output, when you feed in context from an agentic session, naturally the llm has no way of determining what was ITS previous input or what is part of a prompt etc. it's all just mixed together. Again I think there is a possible solution there through either using structured outputs or an entirely new mechanism for repetition penalties... also complex though lol.
gin66 commentedon Mar 28, 2026
I wonder, if a small 1B llm can be used as repetition detector. Just feed in chunks from the main model's output and ask for detection rating. Could even run as a parallel process.
Only my 2cents about this
bogzbonny commentedon Mar 28, 2026
Cool! The basis of the problem I was actually experiencing is (Qwen3-Coder-Next) would just read a file with a small limit (like 30) over and over and over. My workaround was to just fork opencode and ignore the read limit option if it was provided while not also providing an offset.. worked great
jbmml commentedon Apr 3, 2026
I investigated the loop mechanism in the current codebase and found three contributing factors:
1. MAX_STEPS is a soft limit (prompt.ts:1516)
When
step >= agent.steps, a text message is injected asking the model to stop using tools, but tools are still passed to the provider. Claude models respect this; non-Claude models (MiniMax, Kimi K2, GLM) often ignore it and keep calling tools.A hard fix would be passing an empty tools object on
isLastStep:This would physically prevent tool calls after the step limit regardless of model.
2. Doom loop detection requires user interaction (processor.ts:187-212)
The doom loop detector (threshold=3 identical calls) triggers a
permission.ask()withdoom_looppermission. The default is"ask", but when the user's config has"permission": "allow"(common for headless/automated use), this auto-approves and the loop continues indefinitely.3. Default step limit is Infinity (prompt.ts:1429)
agent.steps ?? Infinitymeans agents without an explicit step limit can loop forever. A sensible default (e.g., 25 or 50) would bound worst-case behavior.I'd like to work on a fix but wanted to confirm the approach first. The minimal change would be (1) — making MAX_STEPS actually disable tools. Would that be acceptable, or do the maintainers prefer keeping it as a soft prompt for Claude compatibility?
isac322 commentedon May 29, 2026
For the “same tool/read call over and over” flavor of this, I published a small OpenCode plugin workaround after reproducing it with Gemini: https://github.com/isac322/opencode-gemini-dejavu / npm: opencode-gemini-dejavu
It is intentionally narrow: it breaks repeated tool-call tails by adding a request-local user boundary and pruning stale prior thought signatures, while preserving the current turn signature.
Artem-Pr commentedon Jul 12, 2026
I hit what appears to be the same repeated-tool-call loop with subagent that uses GLM-5.2
During a code review, the agent repeatedly issued the same two
Readcalls without progressing to the requested section:It was trying to inspect a method around line 1076 in media.repository.ts, but repeatedly requested only the initial range and never advanced with an offset. The identical pair repeated dozens of times until the run was cancelled/exhausted.
This had a direct quota impact:
Environment:
github-actions commentedon Sep 11, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.