★Tool Call ID Duplicated Error: A Complete Troubleshooting Guide for AI Coding Assistants★
If you’ve been using an AI coding assistant and suddenly ran into this error:
HTTP 400: Invalid request: tool call id exec:29 is duplicated
Take a breath. It looks intimidating, but the root cause is actually straightforward. This guide walks you through exactly why it happens, how to track it down, and how to fix it — without needing to touch any source code.
What Does This Error Actually Mean?
When an AI assistant helps you complete tasks, it calls various tools behind the scenes — running commands, reading files, browsing the web, and so on. Every tool call gets assigned a unique identifier called a tool call ID.
The problem occurs when two tool calls sharing the same ID end up in the same conversation history. Some large language model (LLM) APIs treat this as an invalid request and reject it outright with an HTTP 400 error.
In the case we’re examining:
- 🍄
Error message: tool call id exec:29 is duplicated - 🍄
Model: kimi-k2.5 - 🍄
Provider: Moonshot (Kimi’s API) - 🍄
Platform: openclaw
In plain English: the conversation history contained two separate tool calls both labeled exec:29, and the Kimi API refused to process the request.
Why Does This Only Happen with Kimi and Not Other Providers?
This is the question most people ask first. The same workflow runs fine on Anthropic (Claude) or OpenAI, but switching to Kimi immediately triggers the error.
The answer comes down to how strictly different LLM APIs validate incoming requests.
Kimi’s API enforces uniqueness of tool call IDs across the entire conversation history. If it detects a duplicate, it rejects the whole request. Other providers may handle this more leniently, silently ignoring or deduplicating the conflict on their end.
This isn’t a Kimi compatibility issue. It’s actually a bug in the AI assistant platform (openclaw in this case) — specifically in how it generates tool call IDs during retry operations. Kimi’s stricter validation simply exposed a bug that other providers were quietly working around.
How Does the Duplicate Get Into the Conversation History?
Understanding the sequence of events makes the fix much clearer.
Step 1 — Normal execution
The AI assistant runs a file operation. It generates tool call exec:29, executes successfully, and writes the result to the conversation history.
Step 2 — A task fails, triggering a retry
Something goes wrong — maybe a file path doesn’t exist. The assistant’s retry mechanism kicks in automatically.
Step 3 — The ID counter fails to increment
On retry, the platform should generate exec:30. Due to a bug, it generates exec:29 again.
Step 4 — The conversation history becomes corrupted
Both the original exec:29 and the retry’s exec:29 now live in the same conversation history.
Step 5 — Every subsequent request fails
The corrupted history gets sent to the API with every new message. Kimi detects the duplicate and returns a 400 error — every single time.
Step 6 — Restarting doesn’t help
Because conversation history is saved to disk, restarting the gateway doesn’t clear it. The corruption persists across restarts.
This explains why the logs showed different runId values all failing with the exact same error — the problem wasn’t in runtime logic; it was baked into the stored session data.
Step-by-Step: How to Diagnose the Problem
Here’s the full diagnostic process for Windows environments.
Step 1 — Find the Affected Session File
openclaw stores conversation history locally as .jsonl files (JSON Lines format), with one record per line. Run this command to find which file contains the duplicate ID:
Get-ChildItem -Recurse "C:\Users\YourUsername\.openclaw" -Filter "*.jsonl" |
Select-String "exec:29" |
Select-Object Filename, Path
If the same filename appears repeatedly in the results, that’s your problem file.
Step 2 — Count the Duplicate Tool Calls
Once you’ve identified the file, check how many toolCall entries contain exec:29:
$file = "C:\Users\YourUsername\.openclaw\agents\main\sessions\your-session-file.jsonl"
$i = 0
Get-Content $file | ForEach-Object {
$i++
if ($_ -match "exec:29" -and $_ -match "toolCall") {
"Line $i id: $(($_ | ConvertFrom-Json).id) parentId: $(($_ | ConvertFrom-Json).parentId)"
}
}
In a healthy session, exec:29 should appear as a toolCall type exactly once. Multiple appearances confirm the history is corrupted.
Step 3 — Inspect the Raw Records
Take a look at what the original entries actually contain:
$lines = Get-Content $file
$lines[64] | ConvertFrom-Json | ConvertTo-Json -Depth 3
$lines[65] | ConvertFrom-Json | ConvertTo-Json -Depth 3
A normal, healthy pair of records looks like this:
- 🍄
Line 65: role: assistant— contains thetoolCallwith idexec:29 - 🍄
Line 66: role: toolResult— contains the result of the tool execution, referencingexec:29
These two lines form a proper call-and-response pair. The corruption comes from a second exec:29 toolCall that was appended later during a failed retry.
How to Fix It
Option 1 — Isolate the Corrupted Session (Recommended)
The safest approach is to rename the session file so openclaw stops loading it. This preserves the file in case you need it later.
$file = "C:\Users\YourUsername\.openclaw\agents\main\sessions\your-session-file.jsonl"
# Rename instead of delete — keeps your data safe
Rename-Item $file "$file.broken"
Restart the openclaw gateway, start a new conversation, and you’re back in business.
Option 2 — Restore the Session and Switch Providers
If the session contains important conversation history you want to keep:
Rename-Item "$file.broken" $file
After restoring, switch to a different provider (Anthropic Claude or OpenAI) to continue working in that session. These providers handle duplicate IDs more permissively and won’t throw errors.
Option 3 — Manually Edit the Session File (Advanced)
If you’re comfortable with JSON and want to surgically fix the file, open it in a text editor like VS Code, locate the second exec:29 toolCall entry, and delete that line along with its corresponding toolResult line. Always back up the file before editing.
Quick Reference: Which Fix to Use
A Note for Windows Users: grep Doesn’t Work in PowerShell
Many troubleshooting guides reference grep for searching file contents. On Windows, running grep in PowerShell produces this error:
grep : The term 'grep' is not recognized as the name of a cmdlet, function,
script file, or operable program.
The PowerShell equivalent is Select-String. Here’s a quick reference:
# Search all .go files for a keyword
Get-ChildItem -Recurse -Filter "*.go" | Select-String "exec:"
# Search multiple file types at once
Get-ChildItem -Recurse -Include "*.go","*.ts" | Select-String "exec:"
# Show 3 lines of context before and after each match
Get-Content "path\to\file" | Select-String -Context 3,3 "your-keyword"
Think of Select-String as PowerShell’s native grep. Same concept, different syntax.
The Technical Root Cause
For developers and technically curious readers, duplicate tool call ID bugs typically stem from one of three sources:
Retry logic that reuses the previous request context
When a task fails and the agent retries, if it copies the previous request object instead of building a fresh one, it inherits the same tool call IDs.
Conversation history being appended twice
In multi-turn conversations, a bug might cause the same assistant message (containing a toolCall) to be pushed to the history array more than once.
Streaming response handler defects
When processing streamed model output, a flawed handler might collect and write the same toolCall block multiple times before the stream completes.
The openclaw case falls into the first category: the retry mechanism failed to increment the ID counter, generating an identical ID for a new operation.
Frequently Asked Questions
Why does restarting openclaw not fix the error?
Conversation history is stored on disk as .jsonl files. Restarting the gateway process clears memory but doesn’t touch the files. When you reopen the same session, the corrupted history gets loaded again and the same error repeats.
Is this Kimi’s fault or openclaw’s fault?
It’s openclaw’s bug. The duplicate ID shouldn’t have been generated in the first place. Kimi’s API is simply enforcing a rule that the spec requires — tool call IDs within a conversation must be unique. Other providers quietly work around the violation; Kimi correctly rejects it.
Does switching to Claude or GPT mean those models are better?
Not in this context. Those providers happen to be more lenient about this specific validation. That leniency hides the underlying bug rather than fixing it. From a standards-compliance standpoint, Kimi’s behavior is actually more correct.
Will I lose any data by renaming the session file?
No. The .jsonl file remains intact with the .broken extension. You can rename it back at any time to restore access to the conversation history.
What is a .jsonl file?
JSON Lines is a text format where each line is a self-contained, valid JSON object. It’s commonly used for logging and streaming data because you can append records without rewriting the entire file. You can open .jsonl files with any text editor, though VS Code with a JSON extension makes them much easier to read.
How do I prevent this from happening again?
As an end user, the long-term fix needs to come from openclaw’s development team. The most useful thing you can do is file a bug report with the error message tool call id exec:29 is duplicated and a brief description of what triggered it. The more specific the report, the faster developers can isolate and patch the issue.
Key Takeaways
This troubleshooting process follows a straightforward diagnostic pattern that applies well beyond this specific case:
- 🍄
Read the error literally. “ID is duplicated” means exactly that — go find where the duplication lives. - 🍄
Persistent errors that survive restarts point to stored data, not runtime state. When the same error repeats across different sessions and restarts, look at what’s being loaded from disk. - 🍄
Isolate before deleting. Renaming a file gives you a recovery path. Deleting doesn’t. - 🍄
Know your tools. On Windows, Select-Stringdoes whatgrepdoes on Linux and macOS.
If you encounter a similar tool call id duplicated error in any other AI assistant platform, the same logic applies: find the persistent conversation history, search for the duplicate ID, and isolate or repair the affected session file.

