oven-sh/bun · info · TypeError
Aborted
Aborted
Error message
Aborted
What it means
The in-flight request was aborted before completion. It is set when a fetch/request is torn down deliberately: AbortController signal, connection close_and_fail during teardown (src/http/lib.rs:2100, :3938), or the HTTP/2/3 session cancelling the stream (src/http/h2_client/ClientSession.rs:463, :989). is_abort() maps it (and AbortedBeforeConnecting) to CommonAbortReason::UserAbort (src/http/lib.rs:505-510), and JS typically sees it as an AbortError DOMException.
Source
Thrown at src/http/error.rs:6
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
pub enum Error {
#[error("CompressionFailed")]
CompressionFailed,
#[error("Aborted")]
Aborted,
#[error("WriteFailed")]
WriteFailed,
#[error("HTTP2RefusedStream")]
HTTP2RefusedStream,
#[error("HTTP2ContentLengthMismatch")]
HTTP2ContentLengthMismatch,
#[error("HTTP2FrameSizeError")]
HTTP2FrameSizeError,
#[error("HTTP2ProtocolError")]
HTTP2ProtocolError,
#[error("HTTP2FlowControlError")]
HTTP2FlowControlError,
#[error("HTTP2EnhanceYourCalm")]
HTTP2EnhanceYourCalm,
#[error("HTTP2HeaderListTooLarge")]
HTTP2HeaderListTooLarge,
#[error("HTTP2StreamReset")]View on GitHub (pinned to 8c5296ac45)
Solutions
- Confirm the abort is intentional: log signal.reason in the catch block — AbortSignal.timeout gives a TimeoutError reason, user aborts give your own reason.
- If the abort is collateral (session-level), retry idempotent requests with the same body — buffered bodies are reusable.
- For timeout-driven aborts, raise the timeout or use AbortSignal.any to separate user-cancel from deadline.
- Ensure you don't abort a controller shared by multiple fetches unintentionally.
Example fix
// before: abort surprises the caller
const res = await fetch(url, { signal }); // rejects with AbortError, unhandled path
// after: distinguish reasons
try {
const res = await fetch(url, { signal });
} catch (err) {
if (err.name === 'AbortError') {
if (signal.reason?.name === 'TimeoutError') return retry(url);
return; // intentional cancel
}
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (signal?.aborted) throw signal.reason ?? new Error('aborted before start');
const res = await fetch(url, { signal }); Type guard
function isAbortError(err) {
return err instanceof Error && err.name === 'AbortError';
}
function isTimeoutAbort(signal) {
return signal?.reason instanceof Error && signal.reason.name === 'TimeoutError';
} Try / catch
try {
return await fetch(url, { signal });
} catch (err) {
if (isAbortError(err)) {
if (isTimeoutAbort(signal)) return retryWithFreshSignal(url);
return; // user-initiated cancel — swallow
}
throw err;
} Prevention
- Give every fetch its own controller unless shared cancellation is intended
- Separate user-cancel from deadlines via AbortSignal.any([userSignal, AbortSignal.timeout(ms)])
- Always handle AbortError in wrappers so cancellations don't surface as bugs
When it happens
Trigger: Calling abortController.abort() while a fetch is running; a request aborted because its initiator (JS scope) went away; h2 session teardown failing pending waiters with Aborted; S3 helper paths storing Error::Aborted as the terminal request error.
Common situations: React/strict frameworks aborting fetches on unmount; timeout wrappers built on AbortSignal.timeout(); shared h2 connections dropped when a sibling request kills the session; tests that abort requests to verify cancellation handling.
Related errors
- CompressionFailed
- WriteFailed
- HTTP2RefusedStream
- HEAD ${url}: ${head.status}
- Range ${url}: ${res.status}
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/2dd96c92da337a74.
Report an issue: GitHub.