Skip to content

Loop in certain models #3743

Closed as not planned
Closed as not planned

Description

@salavatkhafizov

Description

OC 1.0.10. I get loops with certain models (model keep trying the same tool calling/operation) for extended period of time.

  1. KIMI K2 0905, MiniMax 2 - via chutes.ai
  2. GLM 4.6 via Z.ai coding plan.

sometimes remedy comes from /compact operation, sometimes model needs to be stopped (via Esc, abort request operation).

It would be nice if you can introduce setting for OC to invoke autocompact operation at certain context level (like in CC) - circa 80 % and above

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Activity

  1. added
    opentuiThis relates to changes in v1.0, now that opencode uses opentui
    on Nov 2, 2025
  2. github-actions commented on Nov 2, 2025

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Feel free to ignore if none of these address your specific case.

  3. zenyr commented on Nov 2, 2025

    @zenyr
    Contributor

    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.
    ...
    
  4. removed
    opentuiThis relates to changes in v1.0, now that opencode uses opentui
    on Nov 2, 2025
  5. self-assigned this
    on Nov 2, 2025
  6. rekram1-node commented on Nov 2, 2025

    @rekram1-node
    Collaborator

    We did add some loop detection but as @zenyr points out, there are still some circumstances that it won't quite work

  7. Nindaleth commented on Dec 16, 2025

    @Nindaleth
    Contributor

    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?

  8. rekram1-node commented on Dec 16, 2025

    @rekram1-node
    Collaborator

    can u share the session?

    opencode export > session.json

  9. Nindaleth commented on Dec 16, 2025

    @Nindaleth
    Contributor

    Sure, here's a clean session with the same result (running just the 4 tool calls in this case): session.json

  10. betolink commented on Dec 23, 2025

    @betolink

    Same with GLM 4.7 and opencode 1.0.142

  11. palekiwi commented on Jan 12, 2026

    @palekiwi

    google/gemini-3-pro-preview frequently ends up in a loop such as:

    I'll execute.
    I will write the response.
    I'll execute.
    I will write the response.
    I'll execute.
    I will write the response.
    ...
    
  12. gcc-master commented on Jan 12, 2026

    @gcc-master

    Same with GLM 4.7 and opencode 1.0.142

    Same situation with GLM 4.7 on cerebras.ai

    session.json

    Running session from cli "run" like that

            cmd = [
                "opencode",
                "run",
                section,
                "--agent",
                args.agent,
                "--format",
                "default",
                "--file",
                file_arg,
                "--variant",
                "max"
            ]
    
            result = subprocess.run(cmd, capture_output=True, text=True)
    
  13. 7 remaining items

  14. mindplay-dk commented on Mar 18, 2026

    @mindplay-dk

    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. 🤔

  15. bogzbonny commented on Mar 18, 2026

    @bogzbonny

    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)

  16. mindplay-dk commented on Mar 19, 2026

    @mindplay-dk

    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.)

  17. mindplay-dk commented on Mar 19, 2026

    @mindplay-dk
  18. bogzbonny commented on Mar 19, 2026

    @bogzbonny

    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.

  19. gin66 commented on Mar 28, 2026

    @gin66

    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

  20. bogzbonny commented on Mar 28, 2026

    @bogzbonny

    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

  21. jbmml commented on Apr 3, 2026

    @jbmml

    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?

  22. isac322 commented on May 29, 2026

    @isac322

    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.

  23. Artem-Pr commented on Jul 12, 2026

    @Artem-Pr

    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
  24. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions