{"record":{"id":"d361406bcde76ade","repo":"vercel/next.js","slug":"could-not-determine-origin-for-forwarded-server-ac","errorCode":null,"errorMessage":"Could not determine origin for forwarded Server Actions request. This can happen if port or hostname are not configured for this server.","messagePattern":"Could not determine origin for forwarded Server Actions request\\. This can happen if port or hostname are not configured for this server\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/next/src/server/app-render/action-handler.ts","lineNumber":239,"sourceCode":"  }\n\n  const forwardedHeaders = getForwardedHeaders(req, res)\n\n  // indicate that this action request was forwarded from another worker\n  // we use this to skip rendering the flight tree so that we don't update the UI\n  // with the response from the forwarded worker\n  forwardedHeaders.set('x-action-forwarded', '1')\n\n  // TODO: Remove __NEXT_PRIVATE_ORIGIN\n  let origin: string | undefined = process.env.__NEXT_PRIVATE_ORIGIN\n  if (origin === undefined) {\n    const initUrl = getRequestMeta(req, 'initURL')\n    if (initUrl !== undefined) {\n      try {\n        const parsedUrl = new URL(initUrl)\n        origin = parsedUrl.origin\n      } catch (error) {\n        throw new Error(\n          'Could not determine origin for forwarded Server Actions request. This can happen if port or hostname are not configured for this server.',\n          { cause: error }\n        )\n      }\n    } else {\n      throw new InvariantError('Missing initURL')\n    }\n  }\n\n  const fetchUrl = new URL(`${origin}${basePath}${workerPathname}`)\n\n  try {\n    let body: BodyInit | ReadableStream<Uint8Array> | undefined\n    if (\n      // The type check here ensures that `req` is correctly typed, and the\n      // environment variable check provides dead code elimination.\n      process.env.NEXT_RUNTIME === 'edge' &&\n      isWebNextRequest(req)","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/app-render/action-handler.ts#L221-L257","documentation":"Raised inside createForwardedActionResponse() when a Server Action must be forwarded to a different worker but the server origin cannot be resolved. The code first checks process.env.__NEXT_PRIVATE_ORIGIN; if undefined it tries to derive the origin from the request's initURL via new URL(). If that URL parsing throws, this error is raised with the parse error as cause. It indicates the deployment is missing the private origin/host configuration needed for inter-worker action forwarding.","triggerScenarios":"A Server Action request arrives at a worker that does not own the action (multi-worker/self-hosted Next.js), so createForwardedActionResponse is invoked. __NEXT_PRIVATE_ORIGIN is not set, and getRequestMeta(req,'initURL') returns a value that is not a valid absolute URL (e.g. a relative path, or undefined-leading-to-the-else-branch won't hit this but a malformed URL will). new URL() throws and this error propagates.","commonSituations":"Self-hosted Next.js behind a load balancer without setting __NEXT_PRIVATE_ORIGIN; a custom server or standalone output where hostname/port env vars are absent; misconfigured platform that passes a relative or malformed initURL. Common after migrating from Vercel (which sets these) to a self-hosted runtime.","solutions":["Set the __NEXT_PRIVATE_ORIGIN environment variable to the server's reachable origin, e.g. 'http://localhost:3000' (or the internal host:port). This is the primary documented fix.","Ensure the runtime has a valid HOSTNAME and PORT configured so the request initURL can resolve to an absolute URL.","If using a custom server or standalone mode, verify the server binds to a concrete host/port and that initURL metadata is populated.","On platforms, confirm the platform adapter forwards the correct host/initURL metadata to Next.js."],"exampleFix":"// before: missing origin env\n// (no __NEXT_PRIVATE_ORIGIN set)\n\n// after: set the private origin for inter-worker forwarding\n// __NEXT_PRIVATE_ORIGIN=http://localhost:3000","handlingStrategy":"validation","validationCode":"// Validate env before booting the server in multi-worker setups.\nfunction assertActionForwardingConfig() {\n  if (process.env.__NEXT_PRIVATE_ORIGIN === undefined && !process.env.HOSTNAME) {\n    throw new Error('Set __NEXT_PRIVATE_ORIGIN or HOSTNAME for Server Action forwarding')\n  }\n}","typeGuard":"function isAbsoluteUrl(value: unknown): value is string {\n  if (typeof value !== 'string') return false\n  try { new URL(value); return true } catch { return false }\n}","tryCatchPattern":null,"preventionTips":["Set __NEXT_PRIVATE_ORIGIN in all self-hosted/multi-worker deployments.","Document required env vars (HOSTNAME, PORT, __NEXT_PRIVATE_ORIGIN) in your deployment runbook.","Add a startup health check that fails fast if origin cannot be derived.","Test Server Action forwarding in staging with the same env as production."],"tags":["server-actions","deployment","configuration","self-hosted"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}