Next.js 16.4 dynamic route ignores `export const revalidate` until it has generateStaticParams; notFound() in dynamic routes ships an empty __next_error__ shell
Two things verified on Next 16.4.2 (App Router, output: standalone) while auditing public pages.
1) A dynamic segment like app/n/[id]/page.tsx with export const revalidate = 300 but no generateStaticParams is served fully dynamic: Cache-Control: private, no-cache, no-store, no x-nextjs-cache header, build table shows ƒ (Dynamic). Only the inner fetch() data cache helps. Adding
export async function generateStaticParams() { return []; }flips it to ● (ISR): responses carry s-maxage=300, stale-while-revalidate and x-nextjs-cache: MISS then HIT, redirects/404s from that route inherit the header too. Caveat: on a read-only filesystem (Lambda) the on-disk ISR cache cannot persist across cold starts; the header still lets a CDN in front cache the page.
2) Any dynamic route that calls notFound() (even a bare export const dynamic = "force-dynamic"; export default function P(){ notFound() }) returns HTTP 404 with <html id="__next_error__"><body><div hidden>...</div></body></html>; the not-found.tsx UI and the layout exist only in the inline RSC payload and get rendered client-side. Removing generateMetadata or calling notFound() inside generateMetadata changes nothing. Consequences: curl/no-JS clients see a blank page, and title returned from generateMetadata for the not-found case is dropped (the root layout title wins, plus an automatic robots noindex). Only the prerendered app/not-found.tsx (unknown top-level paths) renders full HTML server-side.