[BUG] `/code-review` tells its background agent to call `ReportFindings`, which the background agent doesn't have

Status Fixed / completed
Reported on v2.1.217
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Aug 5, 2026 · closed Aug 17, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The /code-review command only _sometimes_ invokes the ReportFindings tool.

The command prompts the background agent:

When you are done, submit at most 15 findings via the ReportFindings tool, filling its fields as defined […]

But the background agent always reports something like:

Note: no ReportFindings tool is available in this session (ToolSearch returns no match), so findings are reported inline below.

And then the parent session:

  • invokes ReportFindings itself, or
  • presents the results as prose,
  • only sometimes mentions the background agent was missing the tool

What Should Happen?

The review agent should be able to call ReportFindings.

Or it is never told to.

Error Messages/Logs

No error is raised. But from the review agent's own transcript
(~/.claude/projects/<project>/<session>/subagents/agent-<id>.jsonl):

# the prompt the background agent received
When you are done, submit at most 15 findings via the ReportFindings tool, filling its
fields as defined - for each: the file path and start line, a severity, and a comment
that states the issue and the concrete scenario in which the code misbehaves.

# its first tool call
{"name": "ToolSearch", "input": {"query": "select:ReportFindings", "max_results": 3}}

# its conclusion
Note: no `ReportFindings` tool is available in this session (ToolSearch returns no
match), so findings are reported inline below.

Steps to Reproduce

  1. Build a minimal repo with a defect in the working tree:

```sh
rm -rf /tmp/rf-repro && mkdir -p /tmp/rf-repro && cd /tmp/rf-repro
git init -q && git config user.email repro@example.com && git config user.name Repro
cat > cart.py <<'PY'
def total(items):
"""Sum the price of each item."""
return sum(item["price"] for item in items)
PY
git add cart.py && git commit -qm "add cart total"
cat > cart.py <<'PY'
def total(items, discount=0):
"""Sum the price of each item, applying a percentage discount."""
subtotal = sum(item["price"] for item in items)
return subtotal - discount

def checkout(items, coupon):
# coupon is a percentage, e.g. 10 for 10% off
return total(items, coupon)
PY
```

  1. Start an interactive session with your own configuration excluded, so hooks, plugins and settings are ruled out:

``sh
cd /tmp/rf-repro && claude --setting-sources ""
``

  1. Run /code-review medium. Any level above low works; low never uses the structured path.
  1. Note the output line Running in the background as @code-review.
  1. Do not judge by the rendered findings panel. The parent session often re-reports and masks the failure. Read what the review agent itself returned:

``sh
grep -o 'ReportFindings[^"]\{0,80\}' /private/tmp/claude-501/*/*/tasks/*.output
``

The <output-file> in the task notification is a symlink to the agent's transcript. Expected output: the agent's ToolSearch select:ReportFindings probe, and its "no ReportFindings tool is available in this session" line.

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.217 (assumed, not tested)

Claude Code Version

2.1.222 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

Reproduced in cmux.app and Terminal.app, with claude --setting-sources ""

Since 2.1.218, /code-review runs as a background subagent. Background subagents keep only a fixed allowlist of built-in tools, and ReportFindings is not on it. But the review prompt is still composed against the parent session's tool list, where ReportFindings is present, so the prompt instructs the review agent to submit its findings through a tool that its own dispatch mode has already removed.

Every /code-review run therefore ends with the review agent discovering it cannot report, and falling back to prose.

Two changelog entries in 2.1.218 introduce this:

Changed /code-review to run as a background subagent, so review work no longer fills your conversation and keeps stacked slash commands as its review target
Changed skills with context: fork to run in the background by default; opt out per skill with background: false

The documented background: false opt-out is not reachable here, because /code-review is a built-in command rather than a file-backed skill, so there is no frontmatter to set.

The tool-stripping itself is documented and presumably intended (docs/en/sub-agents):

Apart from Agent and ExitPlanMode [...] a background subagent keeps every MCP tool but only these built-in tools: Read, Grep, Glob, Bash, PowerShell, Edit, Write, NotebookEdit, WebFetch, WebSearch, TodoWrite, Skill, ToolSearch, EnterWorktree, ExitWorktree, Monitor, TaskStop, SendMessage, and Artifact. Claude Code removes every other built-in tool from a background subagent, whether inherited or listed in the tools field [...] The removal reports no error.

ReportFindings is absent from that list.

Why this is easy to miss

The failure is usually invisible in the UI. When the background agent's notification arrives, the parent session might redo the report itself, and the parent does have ReportFindings, so a findings panel renders and the run looks correct.

Across six successful ReportFindings calls in my transcript history, every one came from a parent session after its own background agent had already reported the tool missing. Not once did a review agent call it.

This masking is lossy. In the reproduction below the background agent produced three findings and the parent reported two, silently dropping a real one. The parent had not relayed the review; it re-read the file itself and reported its own, shorter conclusion. The rendered panel looks authoritative either way, so a reviewer cannot tell which they are looking at.

Related issues

  • #80733 asks for a visible warning when the background filter strips a tool. That change probably would have surfaced this.
  • #77146 is a different ReportFindings failure (a 400 when a subagent is resumed from a transcript that names the tool).
  • #83516 and #73939 both concern the presentation of ReportFindings output but assume the call succeeds.

View original on GitHub ↗

3 Comments

yohanan · 2 months ago

A data point that turns this report's "No error is raised" note into a reproducible error, and shows the parent/subagent asymmetry directly.

Observed in an interactive session (not -p), same session, seconds apart:

Main thread — ReportFindings is present in the tool list with a full schema, and a live call succeeds:

ReportFindings({"findings": [], "level": "medium"})
-> No findings reported.

A subagent in that same session — the tool is absent from its system-prompt tool list entirely (its baseline set was Agent, Artifact, Bash, Edit, Read, Skill, ToolSearch, Write), and an actual call attempt fails:

Error: No such tool available: ReportFindings. ReportFindings is disabled for this
session, in subagents as well as here.

The error message's scope claim is false

It asserts the tool is disabled "for this session, in subagents as well as here" — while the parent called it successfully in that same session moments earlier. It is disabled for the subagent only.

This matters beyond cosmetics. The message reads as authoritative about scope, so anyone who hits it concludes the tool is off session-wide and stops looking. Nobody discovers the asymmetry unless they independently probe the parent, which there is no reason to do once the error has "explained" itself. I held the wrong conclusion for over a week on exactly that basis. Either the message should reflect the actual scope, or — if the pruning is unintended — it should be treated as a symptom of it rather than as documentation.

Distinguishing a ToolSearch miss from genuine absence

Worth stating explicitly, because the two are easy to conflate and only one of them is real:

ToolSearch's keyword index covers deferred tools only. A keyword query for a baseline tool therefore returns nothing while the tool is fully present and callable — a true negative about the index, and a false negative about the toolset, with nothing in the result distinguishing them. Only an actual invocation settles it.

This report's repro correctly uses the exact-match select:ReportFindings form. A keyword search would not have been conclusive — I've seen an agent reach the "no ReportFindings tool is available" conclusion from a keyword miss alone while the tool was present the whole time.

Possibly one root cause with three symptoms

This looks like the same shape as:

  • #84125 — LSP pruned from all subagent tool sets in interactive sessions (present in the parent, and in subagents under -p)
  • #85230 — ListMcpResourcesTool / ReadMcpResourceTool unreachable from background subagents

All three are present in parent, absent in subagent, interactive sessions. If that's one mechanism, ReportFindings is a symptom of it rather than its own bug — which would also explain the intermittency.

On intermittency

Consistent with this report's "only sometimes". Over the past ~two weeks I've had several sessions where every subagent lacked the tool, and at least one (2026-08-10) where a code-reviewer subagent had it in its baseline toolset, select:ReportFindings matched, and a live call returned normally. So absence is not a standing subagent restriction — it varies by session, and (per the above) apparently by parent-vs-subagent within a single session.

Practical mitigation for anyone hitting this

Pairing the instruction with an explicit fallback costs one round-trip instead of a lost report: "use ReportFindings directly; if it errors as unavailable or is absent from your toolset, deliver your findings as your final message in the same structure — do not stall, do not truncate, do not silently drop the report." Agents given that recover cleanly. Agents told only to use the tool sometimes treat the instruction as unsatisfiable.

bcherny collaborator · 2 months ago

Thanks for the very precise repro steps. I tested this on 2.1.233 (Linux, terminal) against a throwaway repo with an uncommitted ~20-line diff containing obvious bugs, running /code-review at the default level several times.

In every run the background review agent had the ReportFindings tool and used it — I never saw the "no ReportFindings tool is available" message. Depending on the model, the review either called ReportFindings and then also restated its findings as text, or (by design for some models) reported findings directly as text without calling the tool. In no run was the agent asked to use a tool it didn't have.

One thing worth knowing: a background review reports its findings inside the background agent's own view and then summarizes them into your main conversation as text, so seeing a text summary in the transcript is expected rather than a sign the tool is missing.

The /code-review background-agent behavior was reworked across several recent releases, and the mismatch you saw on ~2.1.22x looks resolved on the current build. Closing as fixed in a recent release — please reply to reopen if you still hit the "no ReportFindings tool" message on the latest version, ideally with a /share of the session so I can see the exact model and tool set.

Changelog: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md

🤖 Generated with Claude Code

github-actions[bot] · 8 days ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.