[BUG] Skill activation emits a second `isMeta` message that orphans the Skill `tool_use` → 400 invalid_request (surfaced as "tool use concurrency")

Open 💬 1 comment Opened Jul 9, 2026 by oppewala

[BUG] Skill activation emits a second isMeta message that orphans the Skill tool_use → 400 invalid_request (surfaced as "tool use concurrency")

What's Wrong?

Activating a skill via the Skill tool intermittently kills the turn with:

API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation.

That user-facing message is misleading. With --debug, the real API error is a plain 400 invalid_request about a broken tool_use/tool_result pairing:

messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: <id>.
Each `tool_use` block must have a corresponding `tool_result` block in the next message.

The orphaned tool_use at messages.2 is the Skill tool call itself.

Root cause

The debug log states it directly:

[INFO]  tool_dispatch_start tool=Skill toolUseId=<id>
[DEBUG] SkillTool returning 2 newMessages for skill skill-creator:skill-creator
[INFO]  tool_dispatch_end tool=Skill toolUseId=<id> outcome=ok
[ERROR] API error: 400 ... messages.2: tool_use ids were found without tool_result blocks immediately after: <id>

SkillTool returns two messages for one activation:

  1. the tool_result for the Skill tool_use, and
  2. a separate isMeta user message containing "Base directory for this skill: …" + the skill's SKILL.md.

When the next request is assembled, that second isMeta message ends up separating the Skill tool_use from its tool_result (the isMeta message's parentUuid skips over the tool_use), so the tool_use is no longer immediately followed by its tool_result. The Messages API rejects the request.

This is the same class of failure as #44596 (an isMeta synthetic message skipping over an orphaned tool_use), and involves the same skill "Base directory" injection described in #64461 — but here it is triggered directly by a single, normal skill activation, not a timeout or a path edge case.

Reproduce

  1. Fresh session (MCP on or off — irrelevant; confirmed with MCP fully disabled).
  2. Ask Claude to activate a skill (repro'd with skill-creator from claude-plugins-official; also fires when skill-creator-primer chains into it).
  3. The turn immediately after the Skill tool call fails with the 400 above.
  4. /rewind is the only recovery — retries stay broken because the malformed message already persists in history.

Debug evidence (two independent repros)

  • Single skill call: request_id req_011CcqZqqC8JaWtM3bgsciVo, orphaned tool_use toolu_01J4BiKZC6wsWLVrEzisc7yK at messages.2, harness line SkillTool returning 2 newMessages for skill skill-creator:skill-creator.
  • Chained (primer → skill-creator): request_id req_011CcqZYbYcvsetFVPtLA5ch, orphaned tool_use toolu_01DbDPEYN398yq6fzCRBoCa2.

Platforms

Reproduces on both Windows (native, PowerShell) and WSL (Linux native), both on 2.1.205 — so this is not platform-, shell-, or install-specific. The two are entirely separate installs with different binaries and different filesystem path formats (C:\… vs /home/…); the "Base directory" path content differs between them yet the failure is identical, confirming the fault is in the cross-platform message-assembly logic, not path handling.

Version

Reproduced on 2.1.205 (native installer) and 2.1.198. In our transcripts every skill-triggered failure is on ≥2.1.198; older builds in the same logs never exercised a skill, so I can't confirm the exact introduction point — but it looks like a recent regression worth bisecting.

Impact

High. Any skill whose activation injects the "Base directory" isMeta message can brick the turn, and because the malformed message persists, the session is unrecoverable without /rewind. The misleading "tool use concurrency" label sends users chasing MCP/parallelism red herrings (see the many unrelated-cause dupes: #40305, #21041, #39818, #51977, #20571).

Suggested fix

Fold the "Base directory / SKILL.md" content into the tool_result block for the Skill call instead of emitting it as a separate isMeta message, so the tool_usetool_result adjacency the Messages API requires is preserved. Separately, the generic 400 → "tool use concurrency" mapping should be narrowed so this surfaces as the orphaned-tool_use error it actually is.

Related

  • #44596 — same isMeta-orphaning mechanism (different trigger)
  • #64461 — same skill "Base directory" injection

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗