The not-found.tsx File
The not-found.tsx (or not-found.js) file is a special file in the app router that renders a 404 page whenever a route is not matched. If a user navigates to a URL that does not correspond to any defined segment, Next.js renders the not-found.tsx file for the closest matching segment, or the root app/not-found.tsx if no segment matches at all. This file provides a consistent user experience for broken links and missing pages, rather than showing a generic browser error. Placement and inheritance: app/not-found.tsx renders for any unmatched URL in the entire app. app/segment/not-found.tsx renders for any unmatched URL under /segment. If a child segment has its own not-found.tsx, it takes precedence over the parent. If no segment has a not-found.tsx, Next.js renders its default 404 page. Using notFound() in page logic: In addition to the file-based approach, you can call the notFound() function inside a server component or page to indicate that a specific record or resource is missing. This is useful when data fetching determines that a resource does not exist (e.g., a database query returns no results for a given ID). When notFound() is called: The behavior is identical to the file-based not-found.tsx approach. The notFound() function throws a special error that Next.js catches and renders the not-found.tsx file. The digest prop is available in the not-found.tsx component for consistent error keys. Returning 404 from the server: For API routes or server actions, you can return a 404 status code to indicate the resource was not found. This is useful for crawlers and API consumers. Example: // pages/api/products/[id].js (Pages Router example) export default function handler(req, res) { const product = findProduct(req.id) if (!product) { res.status(404).json({ error: 'Product not found' }) return } res.json(product) } Interview framing: When asked about 404 handling, a strong answer explains three mechanisms: (1) the not-found.tsx file for route-level 404s, (2) the notFound() function for data-driven 404s within a page, and (3) returning status(404) from API routes for crawler-friendly responses. Mentioning that notFound() throws a special error that Next.js catches and renders the not-found.tsx shows deep understanding. Discussing the digest prop for consistent error keys across shows attention to detail. Typical interview question: "How do you handle 404 pages in Next.js?" A strong answer covers all three mechanisms and explains the trade-offs: the file-based not-found.tsx is best for route-level 404s, the programmatic notFound() is best when data fetching determines a resource is missing, and returning status(404) from API routes is best for API consumers and crawlers. Another common question: "Can a client component call notFound()?" The answer is yes, but only if the component is a server component or runs on the server. The notFound() function must be called in a server context for it to work correctly. The digest prop helps with consistent error keys and logging across all three mechanisms.\n\nWhy the file-based approach matters: The not-found.tsx file provides a consistent, app-wide mechanism for handling 404s. It ensures that every unmatched URL renders a proper 404 page, rather than showing a browser default error or a white screen. This is important for user experience, SEO, and maintaining a professional appearance even when pages are missing.\n\nWhy the programmatic approach matters: The notFound() function provides a way to handle 404s programmatically, which is essential when data fetching determines that a specific resource is missing. This is common in applications that display dynamic content, such as user profiles, product pages, or blog posts. When a database query returns no results, calling notFound() signals to Next.js that the resource does not exist, and the framework renders the appropriate 404 page.\n\nWhy the API route approach matters: Returning status(404) from API routes is essential for API consumers and crawlers who need explicit status codes to understand that the requested resource does not exist. This is different from rendering an HTML 404 page; it's about providing a machine-readable response that can be parsed by clients, search engines, and other services.\n\nInterview quick summary: Three mechanisms for 404 handling: (1) file-based not-found.tsx for route-level 404s, (2) programmatic notFound() for data-driven 404s, (3) status(404) from API routes for crawler-friendly responses. Key point: notFound() throws an error Next.js catches and renders not-found.tsx. The digest prop is available for consistent error keys and logging. Child segment not-found.tsx takes precedence over parent.
Interview Framework for 404 Handling
When asked about 404 handling, a strong answer explains three mechanisms: (1) the not-found.tsx file for route-level 404s, (2) the notFound() function for data-driven 404s within a page, and (3) returning status(404) from API routes for crawler-friendly responses. Mentioning that notFound() throws a special error that Next.js catches and renders the not-found.tsx shows deep understanding. Discussing the digest prop for consistent error keys across shows attention to detail. Typical interview question: "How do you handle 404 pages in Next.js?" A strong answer covers all three mechanisms and explains the trade-offs: the file-based not-found.tsx is best for route-level 404s, the programmatic notFound() is best when data fetching determines a resource is missing, and returning status(404) from API routes is best for API consumers and crawlers. Another common question: "Can a client component call notFound()?" The answer is yes, but only if the component is a server component or runs on the server. The notFound() function must be called in a server context for it to work correctly. The digest prop helps with consistent error keys and logging across all three mechanisms.\n\nInterview quick answers: Three mechanisms for 404: file-based not-found.tsx, programmatic notFound(), API status(404). notFound() throws an error Next.js catches and renders not-found.tsx. digest prop available for consistent error keys. Child segment not-found.tsx takes precedence over parent.\n\nAnother common question: "Where does the segment-specific not-found.tsx take precedence?" The answer is: it takes precedence over the parent segment's not-found.tsx. If a user navigates to a URL under /dashboard and both app/dashboard/not-found.tsx and app/not-found.tsx exist, the segment-specific one (app/dashboard/not-found.tsx) is rendered. This allows for segment-specific 404 pages while maintaining an app-wide fallback.\n\nTypical interview scenario: An interviewer asks: "Your application needs to handle 404 pages for different sections differently. How would you approach this?" A strong answer: "I'd use segment-specific not-found.tsx files for each section, with the root app/not-found.tsx as a fallback. I'd also use the notFound() function programmatically when data fetching determines a resource is missing, and return status(404) from API routes for API consumers. This provides comprehensive 404 handling at all levels."\n\nKey takeaway: The file-based approach is best for route-level 404s, the programmatic approach is best when data fetching determines a resource is missing, and the API route approach is best for API consumers and crawlers. Understanding when to use each mechanism demonstrates deep understanding of Next.js error handling.\n\nDigest prop: The digest prop provides a string summary of the error, useful for consistent error keys and logging across all three mechanisms. It helps with debugging and ensures that the same error always renders the same 404 page.\n\nInterview note: When discussing 404 handling in interviews, emphasize that Next.js provides three complementary mechanisms, and the best approach often involves using all three depending on the context. This shows you understand the full spectrum of error handling options in the Next.js app router.\n\nSEO consideration: Proper 404 handling is also important for SEO. Search engines like Google expect a valid 404 status code and a proper HTML page when a page is not found. Using Next.js's built-in 404 handling ensures that your application meets these expectations and doesn't inadvertently soft-404 (return a 200 status code for a non-existent page), which can confuse search engines and harm your site's indexing.\n\nPerformance consideration: The not-found.tsx file is rendered on the server, which means it benefits from server-side rendering performance. The HTML is sent to the client immediately, rather than waiting for a client-side fetch or API call. This improves the perceived performance of your 404 pages and ensures that users (and search engine crawlers) get a consistent experience.\n\nAccessibility consideration: When rendering a 404 page, it's important to include proper accessibility markup, such as a meaningful heading, a description of what happened, and links to help the user navigate back to valid pages. This ensures that all users, including those using screen readers, understand what happened and can find their way back to valid content.\n\nSummary: Next.js provides three mechanisms for handling 404 pages: file-based not-found.tsx, programmatic notFound(), and API route status(404). Each has its use case, and understanding when to use each demonstrates deep understanding of the framework. The digest prop is available across all three mechanisms for consistent error keys and logging. Proper 404 handling is important for user experience, SEO, and accessibility.
Using notFound() in Page Logic
In addition to the file-based approach, you can call the notFound() function inside a server component or page to indicate that a specific record or resource is missing. This is useful when data fetching determines that a resource does not exist (e.g., a database query returns no results for a given ID). When notFound() is called: The behavior is identical to the file-based not-found.tsx approach. The notFound() function throws a special error that Next.js catches and renders the not-found.tsx file (or the default 404 page if none exists). The digest prop is available in the not-found.tsx component for consistent error keys and logging. Typical interview question: "How do you handle 404 pages in Next.js?" A strong answer covers all three mechanisms: file-based not-found.tsx, programmatic notFound(), and API status(404). The file-based approach is best for route-level 404s where no segment matches. The programmatic notFound() is best when data fetching determines a resource is missing. Returning status(404) from API routes is best for API consumers and crawlers who need explicit status codes. The notFound() function throws a special error that Next.js catches and renders the not-found.tsx file (or the default 404 page if none exists). The digest prop is available for consistent error keys and logging across all mechanisms.\n\nHow notFound() works internally: When notFound() is called, it throws a special React error with a special error name (MODULE_NOT_FOUND in some cases, or a custom error type). Next.js's error boundary machinery catches this error and renders the not-found.tsx file for the closest matching segment. The error object passed to the not-found.tsx component includes the original error and a digest string. The digest is a concise summary that can be used as a key for consistent rendering. If the same error occurs multiple times, the same digest ensures that the same 404 page is rendered, which is useful for caching and logging.\n\nCode example: Consider a product detail page that fetches a product by ID:\n\njsx\n// app/products/[id]/page.js – server component\nimport { notFound } from 'next\n\nexport default async function ProductPage({ params }) {\n const product = await prisma.product.findUnique({\n where: { id: params.id }\n })\n if (!product) {\n notFound()\n }\n return (\n <div>\n <h1>{product.name}</h1>\n <p>{product.description}</p>\n </div>\n )\n}\n\n\nWhy this pattern is useful: Calling notFound() in page logic is useful when you want to indicate that a specific resource is missing, rather than rendering a generic 404 page. For example, if a user navigates to a product page and the product no longer exists, you can call notFound() to render a 404 page that indicates the specific product is missing. This is more informative than a generic 404 page and provides a better user experience.\n\nComparison with file-based approach: The programmatic notFound() approach has the same behavior as the file-based not-found.tsx approach. The main difference is that notFound() allows you to conditionally trigger a 404 based on runtime data, while the file-based approach is always active for unmatched URLs. Both approaches result in the same rendering of the not-found.tsx file (or the default 404 page).\n\nInterview framing: When asked about programmatic 404 handling, a strong answer explains that notFound() throws a special error that Next.js catches and renders the not-found.tsx file. Mentioning the digest prop shows attention to detail. Discussing the trade-offs between the file-based and programmatic approaches demonstrates depth. Interviewers also appreciate candidates who can explain why they would choose one approach over the other in different scenarios.\n\nWhen to use each approach: Use the file-based not-found.tsx for route-level 404s where no segment matches. Use the programmatic notFound() when data fetching determines a specific resource is missing. Use return status(404) from API routes for API consumers and crawlers. Understanding when to use each mechanism demonstrates deep understanding of Next.js error handling.\n\nKey takeaway: notFound() throws a special error Next.js catches and renders not-found.tsx. The digest prop is available for consistent error keys and logging. Both programmatic and file-based approaches have identical rendering behavior.
Quiz
1. Which of the following renders a 404 page for an unmatched URL in the app router?
2. What does calling notFound() inside a page do?
3. What prop is available in not-found.tsx from calling notFound()?
4. How can you return a 404 status from an API route?
Flashcards
Question
Which file renders a 404 for unmatched URLs in the app router?
Click to reveal answer
Answer
not-found.tsx (or the default Next.js 404 page if none exists).
Question
What does the programmatic notFound() function do?
Click to reveal answer
Answer
Throws a special error that Next.js catches and renders the not-found.tsx file.
Question
What digest prop is available in not-found.tsx when notFound() is called programmatically?
Click to reveal answer
Answer
A string summary of the error, useful for consistent keys and logging.
Question
How do you return a 404 status from an API route?
Click to reveal answer
Answer
res.status(404).json({ error: 'Not found' }).
Question
Which not-found.tsx takes precedence if both parent and child exist?
Click to reveal answer
Answer
Child segment not-found.tsx takes precedence over the parent.
Revision Notes
Key Takeaways
- 1. File-based 404: app/not-found.tsx app-wide, app/segment/not-found.tsx under that segment
- 2. Child segment not-found.tsx takes precedence over parent
- 3. Programmatic 404: notFound() function in server component/page
- 4. Identical behavior to file-based approach
- 5. API routes: res.status(404).json({ error: 'Not found' })
Interview Tips
- • Three mechanisms for 404: file-based not-found.tsx, programmatic notFound(), API status(404)
- • notFound() throws an error Next.js catches and renders not-found.tsx
- • digest prop available for consistent error keys
- • Child segment not-found.tsx takes precedence over parent
Cheat Sheet
404 Handling Cheat Sheet
File-based 404:
app/not-found.tsxapp-wide,app/segment/not-found.tsxunder that segment- Child segment
not-found.tsxtakes precedence over parent
Programmatic 404:
notFound()function throws error that Next.js catches and rendersnot-found.tsx- Identical behavior to file-based approach
API Routes:
res.status(404).json({ error: 'Not found' })
Interview quick answers:
- Three mechanisms for 404: file-based
not-found.tsx, programmaticnotFound(), APIstatus(404) notFound()throws an error Next.js catches and rendersnot-found.tsxdigestprop available for consistent error keys- Child segment
not-found.tsxtakes precedence over parent