remix-run/react-router · error · Error

${method}() call aborted without an `AbortSignal.reason`: ${

Error message

${method}() call aborted without an `AbortSignal.reason`: ${request.method} ${request.url}

What it means

`createStaticHandler.query()`/`queryRoute()` noticed `request.signal.aborted` but `signal.reason` is `undefined`, so there is no underlying error to rethrow. The handler throws a synthetic Error naming the method (`query`/`queryRoute`) and the aborted request so the caller can see *which* call was aborted.

Source

Thrown at packages/react-router/lib/router/router.ts:5092

  return {
    ...handlerContext,
    statusCode: isRouteErrorResponse(error) ? error.status : 500,
    errors: {
      [errorBoundaryId]: error,
    },
  };
}

function throwStaticHandlerAbortedError(
  request: Request,
  isRouteRequest: boolean,
) {
  if (request.signal.reason !== undefined) {
    throw request.signal.reason;
  }

  let method = isRouteRequest ? "queryRoute" : "query";
  throw new Error(
    `${method}() call aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`,
  );
}

function isSubmissionNavigation(
  opts: BaseNavigateOrFetchOptions,
): opts is SubmissionNavigateOptions {
  return (
    opts != null &&
    (("formData" in opts && opts.formData != null) ||
      ("body" in opts && opts.body !== undefined))
  );
}

function defaultNormalizePath(request: Request): Path {
  let url = new URL(request.url);
  return {
    pathname: url.pathname,

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Abort with a reason: `controller.abort(new Error('user navigated away'))` so the reason is propagated instead of the synthetic message.
  2. If the abort is expected (client disconnect), catch and treat as a no-op rather than an error.
  3. Upgrade Node/runtime to a version that always populates `signal.reason`.

Example fix

// before
controller.abort();

// after
controller.abort(new DOMException('User navigated away', 'AbortError'));
Defensive patterns

Strategy: try-catch

Validate before calling

const controller = new AbortController();
controller.abort(new DOMException('Reason', 'AbortError')); // always pass a reason
const request = new Request(url, { signal: controller.signal });

Try / catch

try {
  await staticHandler.query(request);
} catch (e) {
  if (e instanceof Error && e.message.includes('aborted without an `AbortSignal.reason`')) {
    // expected abort, ignore
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Caller aborts the `Request`'s `AbortSignal` without a reason (e.g. `controller.abort()` with no argument) while a static `query()`/`queryRoute()` is running, and the abort is observed by `throwStaticHandlerAbortedError`.

Common situations: Server-side rendering where the client disconnects and the framework aborts the request; calling `controller.abort()` directly without passing an Error; using an older runtime that doesn't populate `AbortSignal.reason`.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/559a2270db71da2a. Report an issue: GitHub.