can1357/oh-my-pi · warning · AbortError
AbortError
Error message
AbortError
What it means
This AIError.AbortError is thrown when the Anthropic stream ends without any events while the caller had aborted the request. After a stream-termination condition the library first checks local timeout aborts and then whether the caller aborted, and surfaces a clean AbortError instead of a generic stream error.
Source
Thrown at packages/ai/src/providers/anthropic.ts:2659
}
} else {
calculateCost(model, output.usage);
}
}
} else if (event.type === "message_stop") {
sawTerminalEnvelope = true;
sawMessageStop = true;
// The protocol is complete even if a broken keep-alive leaves the HTTP body open.
break;
}
}
const firstEventTimeoutError = activeAbortTracker.getLocalAbortReason();
if (firstEventTimeoutError) {
throw firstEventTimeoutError;
}
if (activeAbortTracker.wasCallerAbort()) {
throw new AIError.AbortError();
}
if (!sawEvent || !sawMessageStart) {
throw new AIError.AnthropicStreamEnvelopeError("stream ended before message_start");
}
if (!sawTerminalEnvelope) {
// Neither a message_delta stop_reason nor message_stop arrived: the
// connection died mid-generation. Finalizing the partial message as
// a clean "stop" would make the agent loop treat the truncated turn
// as complete (silent mid-sentence halt), so fail the turn. The
// envelope error is transparently retried before replay-unsafe
// content streams; afterwards it surfaces as an error turn whose
// complete tool calls the agent loop salvages
// (`recoverTransientErrorToolTurn` recognizes the envelope-error
// text and `retainCompletedToolCalls` drops half-streamed calls).
throw new AIError.AnthropicStreamEnvelopeError("stream ended before message_stop");
}
if (!sawMessageStop) {
// A stop_reason arrived via message_delta, so generation finished;View on GitHub (pinned to 9690622007)
Solutions
- Expected behavior on cancellation — handle AbortError distinctly from real failures and treat it as a cancelled turn.
- If unintended, increase or remove the AbortSignal timeout so the model has time to emit the first event.
- Check code paths that abort the signal (UI cancel buttons, orchestration timeouts) if cancellation was not expected.
- Retry the request if the abort was caused by an aggressive deadline; consider streaming-first-token timeouts instead.
Example fix
// before
const res = await streamAnthropic({ prompt }); // no signal, random teardown aborts
// after
const controller = new AbortController();
try {
const res = await streamAnthropic({ prompt, signal: controller.signal });
} catch (err) {
if (err instanceof AIError.AbortError) return; // cancelled, not a failure
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (signal?.aborted) {
return; // don't start a stream that will immediately be aborted
} Type guard
function isAbortError(err: unknown): err is AIError.AbortError {
return err instanceof AIError.AbortError || (err instanceof Error && err.name === "AbortError");
} Try / catch
try {
for await (const event of stream) {
handle(event);
}
} catch (err) {
if (err instanceof AIError.AbortError) {
return; // cancellation is expected, not a failure
} else {
throw err;
}
} Prevention
- Treat AbortError as a control-flow signal, not an error, in agent/UI layers.
- Set first-token timeouts generously (models can take many seconds before the first event).
- Use AbortController per request and abort only from intentional cancel paths.
- Use AbortSignal.timeout() with a margin above p99 time-to-first-token.
When it happens
Trigger: The caller's AbortSignal fired (activeAbortTracker.wasCallerAbort() is true) and the SSE stream then terminated before any event was processed — e.g. user cancellation, request timeout, or application shutdown during a streaming Anthropic call with no first event received.
Common situations: User cancels a generation in the UI; a deadline/AbortSignal.timeout() elapses before the model responds; process shutdown aborts in-flight streams; slow first token causing the caller to abort.
Related errors
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6ba743a142d61dc9.
Report an issue: GitHub.