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

  1. Confirm the abort is intentional: log signal.reason in the catch block — AbortSignal.timeout gives a TimeoutError reason, user aborts give your own reason.
  2. If the abort is collateral (session-level), retry idempotent requests with the same body — buffered bodies are reusable.
  3. For timeout-driven aborts, raise the timeout or use AbortSignal.any to separate user-cancel from deadline.
  4. 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

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


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/2dd96c92da337a74. Report an issue: GitHub.