From 0a557111102556ec1f74dc1b61b2c51662343703 Mon Sep 17 00:00:00 2001 From: Tarun Sukhani Date: Sun, 15 Feb 2026 07:40:34 +0800 Subject: [PATCH] fix: guard against undefined path in bootstrap file entries The session-context hook pushed bootstrap entries without the required `path` property, causing a TypeError in buildInjectedWorkspaceFiles when it called .replace() on undefined. Add fallback to file.name when path is missing, and skip entries with no path in the report builder. Also add stack trace logging to lane task errors and embedded agent failures to make future debugging faster. Co-Authored-By: Claude Opus 4.6 --- src/agents/pi-embedded-helpers/bootstrap.ts | 7 ++++--- src/agents/system-prompt-report.ts | 3 +++ src/auto-reply/reply/agent-runner-execution.ts | 5 ++++- src/process/command-queue.ts | 3 ++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/agents/pi-embedded-helpers/bootstrap.ts b/src/agents/pi-embedded-helpers/bootstrap.ts index 9e589fc15a4..fa7846cdee4 100644 --- a/src/agents/pi-embedded-helpers/bootstrap.ts +++ b/src/agents/pi-embedded-helpers/bootstrap.ts @@ -199,15 +199,16 @@ export function buildBootstrapContextFiles( if (remainingTotalChars <= 0) { break; } + const filePath = file.path ?? file.name; if (file.missing) { - const missingText = `[MISSING] Expected at: ${file.path}`; + const missingText = `[MISSING] Expected at: ${filePath}`; const cappedMissingText = clampToBudget(missingText, remainingTotalChars); if (!cappedMissingText) { break; } remainingTotalChars = Math.max(0, remainingTotalChars - cappedMissingText.length); result.push({ - path: file.path, + path: filePath, content: cappedMissingText, }); continue; @@ -231,7 +232,7 @@ export function buildBootstrapContextFiles( } remainingTotalChars = Math.max(0, remainingTotalChars - contentWithinBudget.length); result.push({ - path: file.path, + path: filePath, content: contentWithinBudget, }); } diff --git a/src/agents/system-prompt-report.ts b/src/agents/system-prompt-report.ts index 5783202e101..406f344fe84 100644 --- a/src/agents/system-prompt-report.ts +++ b/src/agents/system-prompt-report.ts @@ -44,6 +44,9 @@ function buildInjectedWorkspaceFiles(params: { const injectedByPath = new Map(params.injectedFiles.map((f) => [f.path, f.content])); const injectedByBaseName = new Map(); for (const file of params.injectedFiles) { + if (!file.path) { + continue; + } const normalizedPath = file.path.replace(/\\/g, "/"); const baseName = path.posix.basename(normalizedPath); if (!injectedByBaseName.has(baseName)) { diff --git a/src/auto-reply/reply/agent-runner-execution.ts b/src/auto-reply/reply/agent-runner-execution.ts index 482a2d3efb9..112230d253d 100644 --- a/src/auto-reply/reply/agent-runner-execution.ts +++ b/src/auto-reply/reply/agent-runner-execution.ts @@ -540,7 +540,10 @@ export async function runAgentTurnWithFallback(params: { continue; } - defaultRuntime.error(`Embedded agent failed before reply: ${message}`); + const stack = err instanceof Error ? err.stack : undefined; + defaultRuntime.error( + `Embedded agent failed before reply: ${message}${stack ? `\n${stack}` : ""}`, + ); const safeMessage = isTransientHttp ? sanitizeUserFacingText(message, { errorContext: true }) : message; diff --git a/src/process/command-queue.ts b/src/process/command-queue.ts index 9ee4c741719..eb1ab5b6148 100644 --- a/src/process/command-queue.ts +++ b/src/process/command-queue.ts @@ -100,8 +100,9 @@ function drainLane(lane: string) { const completedCurrentGeneration = completeTask(state, taskId, taskGeneration); const isProbeLane = lane.startsWith("auth-probe:") || lane.startsWith("session:probe-"); if (!isProbeLane) { + const stack = err instanceof Error ? err.stack : undefined; diag.error( - `lane task error: lane=${lane} durationMs=${Date.now() - startTime} error="${String(err)}"`, + `lane task error: lane=${lane} durationMs=${Date.now() - startTime} error="${String(err)}"${stack ? `\n${stack}` : ""}`, ); } if (completedCurrentGeneration) {