nextjs-troubleshooting — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited nextjs-troubleshooting (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this systematic approach to diagnose and fix common Next.js issues. Start with the diagnostic decision tree, then drill into the specific problem category.
Issue Type?
├── Build/Deploy Error → Section 1
├── Runtime Error → Section 2
├── Performance Problem → Section 3
├── Data/Caching Issue → Section 4
├── Security/Auth Issue → Section 5
└── Memory/Resource Issue → Section 6Symptom: Build fails with "Error occurred prerendering page" or dynamic API calls during static generation.
Diagnosis: A page being statically generated is calling a runtime API (cookies(), headers(), searchParams) or a dynamic data source without proper configuration.
Fix: Either:
<Suspense> to enable Partial Prerenderingconst dynamic = 'force-dynamic' for fully dynamic pagesSymptom: Build succeeds but runtime errors like "Cannot read property of undefined" or API calls failing in production.
Diagnosis: Variables available in .env.local during dev are not configured in the production environment.
Fix: Verify all required env vars are set in the deployment platform. Use NEXT_PUBLIC_ only for browser-safe values. Check instrumentation.ts for startup validation.
Symptom: "Error: Only plain objects, and a few built-ins, can be passed to Client Components" or silently stripped data.
Cause: Passing non-serializable props from Server to Client Components — Date objects, Map, Set, functions, class instances.
Fix: Convert to serializable types before passing:
// Server Component
const date = await getDate();
return <ClientComponent dateString={date.toISOString()} />;
// Client Component
const date = new Date(dateString);Symptom: "Warning: Text content did not match" or "Hydration failed because the server rendered HTML didn't match the client."
Cause: Server-rendered HTML differs from client-rendered output. Common triggers:
Date.now() or Math.random() in renderwindow or localStoragetypeof window !== 'undefined' checks in render pathFix:
useEffect for browser-only logic (runs only on client)suppressHydrationWarning only for intentional mismatches (e.g., timestamps)useEffect state initializationSymptom: Server Component crashes accessing properties on data that should exist.
Diagnosis: Usually a data fetching issue — the query returned null/undefined due to missing auth, wrong params, or database connectivity.
Fix: Add null checks and verify the DAL function returns data. Check auth state. Use TypeScript strict null checks.
Symptom: Page loads slowly despite fast individual queries.
Diagnosis: Sequential await calls where queries don't depend on each other:
// BAD: Waterfall — total time = query1 + query2 + query3
const user = await getUser(id);
const posts = await getPosts(id);
const comments = await getComments(id);Fix: Parallelize independent requests:
// GOOD: Parallel — total time = max(query1, query2, query3)
const [user, posts, comments] = await Promise.all([
getUser(id),
getPosts(id),
getComments(id),
]);Symptom: Slow TTI, large "First Load JS" in build output.
Fix:
@next/bundle-analyzer to identify heavy dependenciesnext/dynamic for below-the-fold interactive componentsSymptom: Largest Contentful Paint > 2.5s.
Fix: Ensure the LCP image uses next/image with priority prop. Remove loading="lazy" from above-the-fold images. Check server response time (TTFB).
Symptom: Form submits successfully but the page shows old data.
Fix: Call revalidatePath() or revalidateTag() in the Server Action after the mutation. Ensure the revalidation target matches the cached route/tag.
Symptom: User logs out but still sees authenticated content, or auth state is stale across navigation.
Cause: layout.tsx does not re-render on sibling navigation — auth checks placed there become stale.
Fix: Move authorization checks to page.tsx or the Data Access Layer. Call the DAL directly in each page that needs auth verification.
Symptom: Data seems frozen, changes don't appear.
Cause: Prior to Next.js 15, fetch was cached by default.
Fix: Upgrade to Next.js 15+ (uncached by default). Or explicitly configure cache: 'no-store' on fetch calls. Use the "use cache" directive for intentional caching.
Symptom: Unauthenticated users accessing protected routes despite middleware checks.
Cause: Middleware can be bypassed via spoofed headers (CVE-2025-29927) or misconfigured matchers.
Fix: Never rely solely on middleware for auth. Re-verify authentication in every Server Action, Route Handler, and DAL function independently.
Symptom: Secret API keys visible in browser DevTools network tab or page source.
Cause: Using NEXT_PUBLIC_ prefix on sensitive variables, or importing a server module into a Client Component.
Fix: Remove NEXT_PUBLIC_ prefix from secrets. Add import 'server-only' to modules with env var access. Restrict process.env to the DAL.
Symptom: Dev server RAM climbs to several GB over time, eventually crashing.
Cause: Known issue with Next.js dev server memory management, especially with large codebases and frequent HMR.
Fix: Restart the dev server periodically. Consider using Turbopack (next dev --turbopack) which has improved memory characteristics.
Symptom: Container killed with OOM (Out of Memory) signal in production.
Cause: Documented linear memory growth in recent Next.js versions when containerized.
Fix:
NODE_OPTIONS="--max-old-space-size=512"Symptom: Server Actions fail intermittently in multi-instance deployments.
Cause: Each instance generates a different encryption key for Server Actions.
Fix: Set NEXT_SERVER_ACTIONS_ENCRYPTION_KEY environment variable consistently across all instances.
When encountering an unknown error:
npm run build && npm run start (dev and prod behave differently).For additional errors not covered above:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.