can1357/oh-my-pi · info · ToolAbortError

Ask input was cancelled

Error message

Ask input was cancelled

What it means

After collecting answers for all questions, the ask tool wraps its await in a catch that converts a DOM-style AbortError (name === 'AbortError') into ToolAbortError('Ask input was cancelled'). This covers the multi-question flow's aggregated prompt being aborted while waiting for input. It rethrows all other errors unchanged.

Source

Thrown at packages/coding-agent/src/tools/ask.ts:984

					}
					const details: AskToolDetails = {
						question: result.question,
						options: result.options,
						multi: result.multi,
						selectedOptions: result.selectedOptions,
						customInput: result.customInput,
						note: result.note,
						timedOut: result.timedOut,
					};
					const responseText = formatSingleQuestionResponse(result);
					return { content: [{ type: "text" as const, text: responseText }], details };
				}
				const details: AskToolDetails = { results };
				const responseText = `User answers:\n${results.map(formatQuestionResult).join("\n")}`;
				return { content: [{ type: "text" as const, text: responseText }], details };
			} catch (error) {
				if (error instanceof Error && error.name === "AbortError") {
					throw new ToolAbortError("Ask input was cancelled");
				}
				throw error;
			}
		}

		const askQuestion = async (
			q: AskParams["questions"][number],
			options?: { previous?: QuestionResult; navigation?: NavigationControls },
		) => {
			const questionOptions = q.options.map(option => ({
				label: option.label,
				...(option.description?.trim() ? { description: option.description.trim() } : {}),
			}));
			const optionLabels = questionOptions.map(getAskOptionLabel);
			try {
				const { selectedOptions, customInput, note, navigation, cancelled, timedOut } = await askSingleQuestion(
					ui,
					q.question,

View on GitHub (pinned to 9690622007)

Solutions

  1. Catch ToolAbortError at the tool-call boundary and treat it as a graceful stop.
  2. Check why the AbortSignal fired if cancellation was unexpected (upstream context.abort(), timeout, or session teardown).
  3. Ensure callers pass a live signal and don't abort the context while the ask prompt is legitimately open.

Example fix

// before
const result = await askTool.execute(params, signal);
// after
let result;
try {
  result = await askTool.execute(params, signal);
} catch (err) {
  if (err instanceof ToolAbortError && /Ask input was cancelled/.test(err.message)) {
    return { cancelled: true };
  }
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling, ensure the signal is not already aborted
if (signal.aborted) return { status: 'cancelled' };

Type guard

function isAbortNamedError(e: unknown): e is Error {
  return e instanceof Error && e.name === 'AbortError';
}

Try / catch

try {
  result = await askTool.execute(params, signal, onUpdate, context);
} catch (err) {
  if (err instanceof ToolAbortError) return { status: 'cancelled' };
  throw err;
}

Prevention

When it happens

Trigger: An AbortError is raised by the underlying prompt/UI call while awaiting the user's answers (e.g. context.abort() from another path, or signal abort from the agent run being cancelled mid-prompt).

Common situations: The agent session is aborted externally while a multi-question ask dialog is open; the user cancels via a UI control that surfaces as a plain AbortError rather than the tool's own cancelled flag.

Related errors


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