can1357/oh-my-pi · error · StructuredSubagentError

Subagent execution failed: ${error instanceof Error ? error.

Error message

Subagent execution failed: ${error instanceof Error ? error.message : String(error)}

What it means

Generic execution-stage wrapper: any error thrown while the subagent actually runs (after preflight/isolation succeed) is wrapped in a StructuredSubagentError at stage "execution" with the original error as `cause`. Existing StructuredSubagentErrors pass through unwrapped, so this only surfaces unexpected failures from the agent run itself.

Source

Thrown at packages/coding-agent/src/task/structured-subagent.ts:664

			else if (result.patchPath)
				mergeSummary = `\n\nIsolation: changes captured at \`${result.patchPath}\` (apply=false). Not applied.`;
			else if ((result.nestedPatches?.length ?? 0) > 0)
				mergeSummary = `\n\nIsolation: changes captured for ${result.nestedPatches?.length} nested ${(result.nestedPatches?.length ?? 0) === 1 ? "repository" : "repositories"} (apply=false). Not applied.`;
			else mergeSummary = "\n\nIsolation: no changes captured.";
		}

		completedSuccessfully = result.exitCode === 0 && !result.error && !result.aborted;
		return {
			result,
			policy,
			mergeSummary,
			changesApplied,
			artifactsDir: lease.artifactsDir,
			temporaryArtifacts: lease.temporary,
		};
	} catch (error) {
		if (error instanceof StructuredSubagentError) throw error;
		throw new StructuredSubagentError(
			"execution",
			`Subagent execution failed: ${error instanceof Error ? error.message : String(error)}`,
			{ cause: error },
		);
	} finally {
		const shouldRetainArtifacts =
			(request.retainArtifacts && completedSuccessfully) ||
			(policy.isIsolated && (!policy.applyChanges || changesApplied === false || requiresRecoveryArtifacts));
		const shouldCleanup = lease.temporary && !shouldRetainArtifacts;
		if (shouldCleanup) {
			const cleanupArtifacts = async (): Promise<void> => {
				await fs.rm(lease.artifactsDir, { recursive: true, force: true });
				lease.unregister?.();
			};
			if (deferredCleanup) {
				trackLateCleanup(deferredCleanup.then(cleanupArtifacts), {
					resource: "artifacts",
					artifactsDir: lease.artifactsDir,

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect `error.cause` (or the message suffix) for the root failure and fix that
  2. Retry the task if the cause was transient (network/provider error)
  3. Add error handling in the subagent's tools/prompts so failures surface as controlled errors

Example fix

// caller handling
try {
  const result = await runStructuredSubagent(req);
} catch (e) {
  if (e instanceof StructuredSubagentError && e.stage === "execution") {
    logger.error("subagent failed", { cause: e.cause }); // inspect and retry if transient
  }
}
Defensive patterns

Strategy: try-catch

Type guard

function isExecutionStageError(e: unknown): e is StructuredSubagentError {
  return e instanceof StructuredSubagentError && e.stage === "execution";
}

Try / catch

try {
  return await runStructuredSubagent(req);
} catch (e) {
  if (isExecutionStageError(e)) {
    logger.error("subagent execution failed", { cause: e.cause });
    if (isTransient(e.cause)) return withRetry(() => runStructuredSubagent(req));
  }
  throw e;
}

Prevention

When it happens

Trigger: The spawned agent run throws — model/API errors, tool crashes, unhandled exceptions inside the subagent loop, aborted sessions — anything not already a StructuredSubagentError.

Common situations: LLM provider outages or auth failures during the run; a tool inside the subagent crashing; bugs in agent prompts/handlers causing unhandled rejections; network interruptions mid-run.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/a0d98856f4b77a6c. Report an issue: GitHub.