vercel/next.js · error · Error

Proxy request aborted [${request.method} ${request.url}]

Error message

Proxy request aborted [${request.method} ${request.url}]

What it means

Thrown by the experimental testmode fetch interceptor when the test proxy responds with api 'abort' or 'unhandled' for a fetch. 'unhandled' means no registered mock matched the request URL/method; 'abort' is an explicit signal from the test to terminate the request. The message includes the original method and URL to help identify which fetch was unmocked.

Source

Thrown at packages/next/src/experimental/testmode/fetch.ts:125

      'next-test-internal': '1',
    },
    next: {
      // @ts-ignore
      internal: true,
    },
  })
  if (!resp.ok) {
    throw new Error(`Proxy request failed: ${resp.status}`)
  }

  const proxyResponse = (await resp.json()) as ProxyResponse
  const { api } = proxyResponse
  switch (api) {
    case 'continue':
      return originalFetch(request)
    case 'abort':
    case 'unhandled':
      throw new Error(
        `Proxy request aborted [${request.method} ${request.url}]`
      )
    case 'fetch':
      return buildResponse(proxyResponse)
    default:
      return api satisfies never
  }
}

export function interceptFetch(originalFetch: Fetch) {
  global.fetch = function testFetch(
    input: FetchInputArg,
    init?: FetchInitArg
  ): Promise<Response> {
    // Passthrough internal requests.
    // @ts-ignore
    if (init?.next?.internal) {
      return originalFetch(input, init)

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Register an httpMockHandler (or use mocked async handler) that matches the exact URL/method of the failing fetch shown in the message.
  2. Loosen the mock matcher (wildcards, regex, ignore query params) so transient differences don't cause an unhandled result.
  3. Use `api: 'continue'` (passthrough) in the handler for fetches you intentionally want to hit the network during tests.
  4. Audit nested dependencies for surprise fetches and either mock or stub them at the module boundary.

Example fix

// before — no mock for /api/user
// fetch('/api/user') in server component -> abort
// after — register a matching mock
const handlers = [
  {
    url: '*/api/user',
    method: 'GET',
    handler: async () => Response.json({ id: 1, name: 'ada' }),
  },
]
Defensive patterns

Strategy: validation

Validate before calling

// Register a catch-all mock that returns 'continue' so unmocked fetches passthrough
const catchAll = { url: '*', handler: async () => ({ api: 'continue' }) }
// or assert all expected fetches are mocked before the test runs

Try / catch

try {
  await runServerAction()
} catch (e) {
  if (/Proxy request aborted/.test(e.message)) {
    console.error('Unmocked fetch detected:', e.message)
    // register the missing mock and retry once
  }
  throw e
}

Prevention

When it happens

Trigger: A server-side fetch() executes during a testmode test, the proxy receives it, but no httpMockHandler matches (or the handler returned 'unhandled'), so the proxy tells Next.js to abort. Triggered per-fetch in app-router or pages-router server code under testmode.

Common situations: Forgetting to mock a fetch that a deep dependency performs (analytics, auth lookup, telemetry); URL pattern mismatch between mock and actual call (trailing slash, query, absolute vs relative); or a mock handler timing out and the test aborting. Also when the test ends before all in-flight fetches resolve.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/49772bacf2b10e07. Report an issue: GitHub.