{"record":{"id":"7d2a496a0e949099","repo":"payloadcms/payload","slug":"forbidden","errorCode":null,"errorMessage":"Forbidden","messagePattern":"Forbidden","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tanstack-start/src/utilities/serverAdapter.server.ts","lineNumber":93,"sourceCode":"  },\n\n  redirect: (path: string) => {\n    // TanStack Router requires throwing the redirect() result directly\n    // eslint-disable-next-line @typescript-eslint/only-throw-error\n    throw redirect({ to: path })\n  },\n\n  permanentRedirect: (path: string) => {\n    // TanStack Router does not have a separate permanent redirect primitive;\n    // fall back to a regular redirect so existing behavior is preserved.\n    // eslint-disable-next-line @typescript-eslint/only-throw-error\n    throw redirect({ to: path })\n  },\n\n  forbidden: () => {\n    // TanStack Router does not have a dedicated forbidden() helper; surface\n    // a generic error so the request boundary still terminates the request.\n    throw new Error('Forbidden')\n  },\n\n  unauthorized: () => {\n    // TanStack Router does not have a dedicated unauthorized() helper; surface\n    // a generic error so the request boundary still terminates the request.\n    throw new Error('Unauthorized')\n  },\n\n  setCookie: (name: string, value: string, options?: CookieOptions) => {\n    setResponseHeader('Set-Cookie', serializeCookie(name, value, options))\n  },\n}\n\n/**\n * Navigation requested during an admin page render, recorded by\n * `createPageRenderServerAdapter`. The admin-page server function reads this\n * after `renderServerComponent` resolves.\n */","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/tanstack-start/src/utilities/serverAdapter.server.ts#L75-L111","documentation":"A plain Error('Forbidden') thrown by the TanStack Start server adapter's forbidden() helper. TanStack Router has no dedicated forbidden primitive, so the adapter surfaces a generic error to terminate the request boundary when framework code calls adapter.forbidden() (e.g. access control denied during an admin page render).","triggerScenarios":"Code in the admin page-render pipeline calls the adapter's forbidden() — typically because an access-control check returned false during a TanStack Start server render of an admin route.","commonSituations":"Access policy returns false for the current user on a TanStack Start admin route; the adapter is used before auth is fully resolved; a custom route guard calls forbidden() incorrectly.","solutions":["Review the access-control logic that triggered forbidden() and confirm the user should indeed be denied.","Ensure the user is authenticated and has the required role before reaching the guarded route.","If using TanStack Start, handle this generic error in your error boundary to render a proper 403 page."],"exampleFix":"// before — generic error, no status\nforbidden: () => {\n  throw new Error('Forbidden')\n},\n\n// after — attach a status for the error boundary to map\nimport { Forbidden } from 'payload'\nforbidden: () => {\n  throw new Forbidden()\n},","handlingStrategy":"try-catch","validationCode":"// The adapter's forbidden() is called by framework access checks;\n// prevent it by ensuring access returns true for authorized users.\nfunction userHasAccess(user: { role?: string } | null, requiredRole: string): boolean {\n  return Boolean(user && user.role === requiredRole)\n}\n\nif (!userHasAccess(req.user, 'admin')) {\n  // handle before the adapter calls forbidden()\n}","typeGuard":"function isAdapterForbidden(err: unknown): err is Error {\n  return err instanceof Error && err.message === 'Forbidden'\n}","tryCatchPattern":"try {\n  await renderAdminPage()\n} catch (err) {\n  if (isAdapterForbidden(err)) {\n    renderForbiddenPage()\n    return\n  }\n  throw err\n}","preventionTips":["Map this generic error in your error boundary to a proper 403 response.","Confirm access-control logic before it reaches forbidden().","Consider replacing the bare Error with Forbidden for type-narrowable handling."],"tags":["tanstack-start","server-adapter","forbidden","access-control","framework"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}