openclaw - 💡(How to fix) Fix Compaction breaks tool_use/tool_result pairing — API rejects orphaned tool_result [3 comments, 4 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#51423Fetched 2026-04-08 01:11:28
View on GitHub
Comments
3
Participants
4
Timeline
5
Reactions
0
Timeline (top)
commented ×3cross-referenced ×2

Session compaction (or context pruning) can remove a tool_use block while leaving its corresponding tool_result in the message history. Anthropic's API then rejects the request with:

messages.80.content.1: unexpected tool_use_id found in tool_result blocks: <id>. 
Each tool_result block must have a corresponding tool_use block in the previous message.

Root Cause

The compactor does not treat tool_use + tool_result as an atomic pair. When truncating history, it can cut at a boundary that preserves a tool_result but drops its preceding tool_use.

Fix Action

Workaround

/reset the affected session, or wait for the daily session reset.

Code Example

messages.80.content.1: unexpected tool_use_id found in tool_result blocks: <id>. 
Each tool_result block must have a corresponding tool_use block in the previous message.
RAW_BUFFERClick to expand / collapse

Summary

Session compaction (or context pruning) can remove a tool_use block while leaving its corresponding tool_result in the message history. Anthropic's API then rejects the request with:

messages.80.content.1: unexpected tool_use_id found in tool_result blocks: <id>. 
Each tool_result block must have a corresponding tool_use block in the previous message.

Impact

The session becomes permanently broken — the agent cannot respond until the session is reset. Owner messages are effectively dropped.

Root Cause

The compactor does not treat tool_use + tool_result as an atomic pair. When truncating history, it can cut at a boundary that preserves a tool_result but drops its preceding tool_use.

Proposed Fix

Compaction and context pruning should treat tool_use/tool_result pairs as indivisible units. Either both survive or both are pruned.

Environment

  • Clawdbot gateway on Ubuntu
  • Anthropic API (Claude Sonnet/Opus)
  • DM session with ~50K tokens, 4 orphaned tool_result references

Workaround

/reset the affected session, or wait for the daily session reset.

Related

  • #50684 (WhatsApp messages dropped during 503 reconnect)

Reporters

Coywolf, Adam (PJ), Jared — observed during Agent University debugging session 2026-03-19/20

extent analysis

Fix Plan

To address the issue, we need to modify the session compaction logic to treat tool_use and tool_result as an atomic pair.

Step-by-Step Solution:

  1. Identify the compaction function: Locate the function responsible for session compaction in the Clawdbot gateway codebase.
  2. Modify the compaction logic: Update the function to check for tool_use and tool_result pairs when truncating the message history.
  3. Implement atomic pair handling: Ensure that both tool_use and tool_result are either preserved or pruned together.

Example Code Snippet (Python):

def compact_session(session):
    # ...
    for i in range(len(session.messages) - 1, -1, -1):
        message = session.messages[i]
        if message.get('tool_result'):
            # Check if corresponding tool_use exists in previous messages
            tool_use_id = message['tool_result']['tool_use_id']
            tool_use_exists = any(msg.get('tool_use', {}).get('id') == tool_use_id for msg in session.messages[:i])
            if not tool_use_exists:
                # Remove the tool_result if tool_use is not found
                session.messages[i] = None
        # ...
    # Remove None values from the session messages
    session.messages = [msg for msg in session.messages if msg]
    # ...

Verification

To verify the fix, test the updated compaction function with a sample session containing tool_use and tool_result pairs. Check that the function correctly preserves or prunes these pairs when truncating the message history.

Extra Tips

  • Ensure that the updated compaction logic is properly tested and validated to avoid introducing new issues.
  • Consider adding logging or monitoring to detect and handle any potential errors or edge cases related to session compaction.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Compaction breaks tool_use/tool_result pairing — API rejects orphaned tool_result [3 comments, 4 participants]