fix: filter empty error messages to prevent session corruption

When 429/500 errors occur during tool execution, empty assistant messages
with stopReason='error' and content=[] get persisted to the session file.

These break the tool_use -> tool_result chain that Claude/Gemini require:
- Claude expects every tool_use block to have a matching tool_result
- Empty error messages inserted mid-sequence violate this invariant
- Results in: 'tool_use ids were found without tool_result blocks'

This patch filters out empty error messages when building session context,
allowing sessions to recover gracefully from transient API errors.

Evidence from production:
- 113 of 170 sessions had empty error messages
- Session 30764430 demonstrated recovery: 429 at 14:30:11 IST,
  resumed successfully at 14:30:22, completed at 14:30:34

Sorry Peter, one more patch! 🙈
This commit is contained in:
Muhammed Mukhthar CM
2026-01-09 09:07:05 +00:00
committed by Peter Steinberger
parent cfcff68e91
commit 1cfe409a09
3 changed files with 27 additions and 3 deletions

View File

@@ -170,7 +170,8 @@
"@sinclair/typebox": "0.34.47"
},
"patchedDependencies": {
"@mariozechner/pi-agent-core": "patches/@mariozechner__pi-agent-core.patch"
"@mariozechner/pi-agent-core": "patches/@mariozechner__pi-agent-core.patch",
"@mariozechner/pi-coding-agent": "patches/@mariozechner__pi-coding-agent.patch"
}
},
"vitest": {

View File

@@ -26,3 +26,23 @@ index 0000000..1111111 100644
}
/** Result from createAgentSession */
export interface CreateAgentSessionResult {
diff --git a/dist/core/session-manager.js b/dist/core/session-manager.js
index b2aba5280d002253b0938b75aedbb9e6e6c4dcf8..67464efff535dbd7a8e6ed825aab2b305ca2aee2 100644
--- a/dist/core/session-manager.js
+++ b/dist/core/session-manager.js
@@ -161,6 +161,15 @@ export function buildSessionContext(entries, leafId, byId) {
const messages = [];
const appendMessage = (entry) => {
if (entry.type === "message") {
+ // PATCH: Filter out empty error assistant messages to prevent session corruption
+ // When 429/500 errors occur during tool execution, empty error messages get persisted
+ // to the session file. These break the tool_use -> tool_result chain for Claude/Gemini.
+ const msg = entry.message;
+ if (msg.role === "assistant" &&
+ msg.stopReason === "error" &&
+ (!msg.content || msg.content.length === 0)) {
+ return; // Skip empty error messages
+ }
messages.push(entry.message);
}
else if (entry.type === "custom_message") {

7
pnpm-lock.yaml generated
View File

@@ -11,6 +11,9 @@ patchedDependencies:
'@mariozechner/pi-agent-core':
hash: 01312ceb1f6be7e42822c24c9a7a4f7db56b24ae114a364855bd3819779d1cf4
path: patches/@mariozechner__pi-agent-core.patch
'@mariozechner/pi-coding-agent':
hash: 58af7c712ebe270527c2ad9d3351fac39d6cd4b81cc475a258d87840b446b90e
path: patches/@mariozechner__pi-coding-agent.patch
importers:
@@ -39,7 +42,7 @@ importers:
version: 0.41.0(ws@8.19.0)(zod@4.3.5)
'@mariozechner/pi-coding-agent':
specifier: ^0.41.0
version: 0.41.0(ws@8.19.0)(zod@4.3.5)
version: 0.41.0(patch_hash=58af7c712ebe270527c2ad9d3351fac39d6cd4b81cc475a258d87840b446b90e)(ws@8.19.0)(zod@4.3.5)
'@mariozechner/pi-tui':
specifier: ^0.41.0
version: 0.41.0
@@ -3807,7 +3810,7 @@ snapshots:
- ws
- zod
'@mariozechner/pi-coding-agent@0.41.0(ws@8.19.0)(zod@4.3.5)':
'@mariozechner/pi-coding-agent@0.41.0(patch_hash=58af7c712ebe270527c2ad9d3351fac39d6cd4b81cc475a258d87840b446b90e)(ws@8.19.0)(zod@4.3.5)':
dependencies:
'@mariozechner/clipboard': 0.3.0
'@mariozechner/pi-agent-core': 0.41.0(patch_hash=01312ceb1f6be7e42822c24c9a7a4f7db56b24ae114a364855bd3819779d1cf4)(ws@8.19.0)(zod@4.3.5)