Capítulo 160 de 456
forbidden() lança um erro que renderiza uma página 403 do Next.js, útil para tratar erros de autorização (usuário autenticado mas sem permissão). Feature experimental, requer flag explícita.
experimental.authInterrupts: true em next.config.js.forbidden() lança NEXT_HTTP_ERROR_FALLBACK;403 e interrompe a renderização do segmento de rota; injeta <meta name="robots" content="noindex" /> automaticamente.await; deixado em promise não aguardada, o throw não é capturado e a UI de forbidden não renderiza.never: não precisa de return forbidden(); um try/catch ao redor suprime o interrupt (use unstable_rethrow para deixar passar).forbidden.js colocado ao lado da rota.import { verifySession } from '@/app/lib/dal'
import { forbidden } from 'next/navigation'
export default async function AdminPage() {
const session = await verifySession()
if (session.role !== 'admin') {
forbidden()
}
return <></>
}
forbidden() diretamente no componente.async function getProjects() {
const session = await verifySession()
if (session?.role !== 'admin') {
forbidden()
}
return db.projects.findMany()
}
// dentro de <Suspense fallback={...}><Projects /></Suspense>
forbidden() dentro de uma Data Access Layer function, envolta em <Suspense>, para manter o shell da página e o loading UI visíveis enquanto a sessão é checada; trade-off é que o status HTTP já começou como 200 antes do throw (streaming já iniciado).forbidden() numa promise sem await: o throw ocorre onde nada captura; em dev aparece como unhandledRejection: NEXT_HTTP_ERROR_FALLBACK;403 no log, e a página forbidden não é exibida.try/catch sem unstable_rethrow: suprime silenciosamente o interrupt e nenhuma UI de erro aparece.forbidden() no root layout: não suportado.<Suspense>: como o streaming já começou como 200, o código de status não pode mudar; para 403 real, o check precisa rodar antes do streaming (ex. em proxy).forbidden() na Data Access Layer, dentro de <Suspense>, quando quiser manter o shell da página visível durante o check de sessão.proxy em vez de dentro do componente.authInterrupts também habilita unauthorized(), a contraparte para usuário não autenticado.authInterrupts.forbidden passar através de um try/catch.