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
- Abort with a reason: `controller.abort(new Error('user navigated away'))` so the reason is propagated instead of the synthetic message.
- If the abort is expected (client disconnect), catch and treat as a no-op rather than an error.
- 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
- Always abort with a reason: `controller.abort(new Error('...'))`.
- Treat client-disconnect aborts in SSR as benign.
- Use a runtime that populates `AbortSignal.reason`.
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
- You cannot call `runClientMiddleware()` from a static handle
- No handlers were found for the request: ${url.pathname}${url
- Prerender: Request timed out for ${prerenderPath}: ${error.m
- Prerender (data): Received a ${response.status} status code
- Cannot write to a destroyed or ended writable stream
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/559a2270db71da2a.
Report an issue: GitHub.