Skip to content

bug(processor): doom loop detection misses cross-message repetitions and has inverted filter order #25254

@qz1543706741

Description

@qz1543706741

Summary

Two bugs in the doom loop detection logic in packages/opencode/src/session/processor.ts allow infinite tool-call loops to go undetected.

Bug 1 — Detection scope limited to current message only

// current code
const parts = MessageV2.parts(ctx.assistantMessage.id)
const recentParts = parts.slice(-DOOM_LOOP_THRESHOLD)

MessageV2.parts(ctx.assistantMessage.id) returns only parts from the current assistant message. When the model repeats the same tool call across multiple turns (e.g. three separate messages each calling read_file with the same path), the doom loop is never detected because each individual message has fewer than DOOM_LOOP_THRESHOLD matching parts.

Expected behavior: Detection should span all messages since the last user turn, not just the current assistant message.

Bug 2 — Slice before filter inverts the logic

// current code
parts.slice(-DOOM_LOOP_THRESHOLD).every(part => part.type === "tool" && part.tool === value.toolName && ...)

Taking the last N parts first (which may include text or reasoning parts) and then checking whether all N match means that if any non-tool part appears in the tail, every returns false and the doom loop check silently passes — even if there are plenty of repeated tool calls.

Expected behavior: Filter matching tool parts first, then check whether the count reaches the threshold.

Proposed Fix

  • Use MessageV2.filterCompactedEffect(ctx.sessionID) to collect matching tool parts across message boundaries since the last user turn.
  • Reorder the logic: filter by tool + JSON(args) first, then slice to DOOM_LOOP_THRESHOLD.

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions