can1357/oh-my-pi · error · ToolError

resultText

Error message

resultText

What it means

In bulk conflict resolution, per-file results are summarized into `resultText`. If every attempted file failed (failedFiles > 0 and succeededFiles === 0), the whole operation is considered failed and the summary text itself is thrown as the ToolError message — the bracketed label 'resultText' is just the logging name for that thrown summary. If some files succeeded, the result is returned normally with isError marked instead.

Solutions

  1. Read the multi-line summary in the error to see each file's specific failure and fix those individually.
  2. Re-read the files to refresh conflict entries, then retry.
  3. Resolve conflicts one at a time (conflict://<id>) to isolate the failing file.
  4. Check whether the target files still exist and contain the expected markers.
Defensive patterns

Strategy: try-catch

Validate before calling

for (const entry of selected) {
  if (!(await Bun.file(entry.absolutePath).exists())) {
    throw new Error(`#${entry.id} target missing — bulk resolve would fail entirely`);
  }
}

Try / catch

try {
  await write("conflict://*", directives);
} catch (err) {
  // err.message is a per-file summary; parse lines and resolve surviving conflicts individually
  for (const line of String(err.message).split("\n")) handleSummaryLine(line);
}

Prevention

When it happens

Trigger: A conflict://* bulk resolve (with or without directives) where every selected file's resolution attempt failed — e.g. all target files missing, all splices failing to match, or every write rejected.

Common situations: Bulk resolve after a branch switch removed all conflicted files; directive content that fails expansion for every entry; permission problems affecting all target paths at once.

Related errors


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

Appendix: source

Thrown at packages/coding-agent/src/tools/write.ts:1095

			);
			for (const file of failedFiles) {
				summaryLines.push(`  ${file.displayPath}: ${file.count} ${conflictWord(file.count)} (${file.error})`);
			}
		}
		const headerLines = succeededFiles
			.map(file => file.header)
			.filter((header): header is string => header !== undefined);
		if (headerLines.length > 0) {
			summaryLines.push("Snapshots:");
			for (const header of headerLines) summaryLines.push(`  ${header}`);
		}
		if (stripped && !directives) {
			summaryLines.push("Note: auto-stripped hashline display prefixes from content before writing.");
		}
		const resultText = summaryLines.join("\n");

		if (failedFiles.length > 0 && succeededFiles.length === 0) {
			throw new ToolError(resultText);
		}
		return {
			content: [{ type: "text", text: resultText }],
			details: {},
			isError: failedFiles.length > 0 ? true : undefined,
		};
	}

	async execute(
		_toolCallId: string,
		{ path: rawPath, content }: WriteParams,
		signal?: AbortSignal,
		onUpdate?: AgentToolUpdateCallback<WriteToolDetails>,
		context?: AgentToolContext,
	): Promise<AgentToolResult<WriteToolDetails>> {
		// Strip a hashline `[path#TAG]` wrapper up front so every downstream
		// decision (scheme routing, internal-URL handler dispatch, plan-mode
		// guard, plan path resolution, ACP bridge routing) sees the same

View on GitHub (pinned to 9690622007)