When running next build (production) vs next dev, API route handlers can silently fail with:
Error: No response is returned from route handler '/path/to/route.ts'.
Ensure you return a `Response` or a `NextResponse` in all branches of your handler.
Even when your code clearly returns a Response, and even when console.log confirms the handler executed successfully.
Next.js 15.5.x has bugs with static Response methods in production builds. The following DO NOT work reliably:
// ❌ BROKEN in production
return Response.json({ data: 'value' });
return Response.json({ error: 'msg' }, { status: 400 });
return NextResponse.json({ data: 'value' });
return Response.redirect('https://example.com');Use the Response constructor directly:
// ✅ WORKS in production
return new Response(JSON.stringify({ data: 'value' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
// ✅ For redirects
return new Response(null, {
status: 302,
headers: { Location: 'https://example.com' },
});| Broken | Fixed |
|---|---|
Response.json(data) |
new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } }) |
Response.json(data, { status: 400 }) |
new Response(JSON.stringify(data), { status: 400, headers: { 'Content-Type': 'application/json' } }) |
NextResponse.json(data) |
Same as above |
Response.redirect(url) |
new Response(null, { status: 302, headers: { Location: url } }) |
PrismaClientInitializationError: Prisma Client could not locate the Query Engine
for runtime "rhel-openssl-3.0.x"
Add binary targets to prisma/schema.prisma:
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "rhel-openssl-3.0.x"]
}And remove @prisma/client from optimizePackageImports in next.config.ts (it conflicts with engine bundling).
Next.js pages can only export specific things. Invalid exports cause routes to silently disappear from the build.
// ❌ BAD - causes route to be skipped
export default function Page() { ... }
export function someUtilityFunction() { ... } // Invalid!
// ✅ GOOD - move utilities to separate file
// page.tsx
export default function Page() { ... }
// lib/utils.ts
export function someUtilityFunction() { ... }When implementing OAuth for MCP (Model Context Protocol) clients like Claude Desktop:
Claude Desktop may register with token_endpoint_auth_method: 'client_secret_post' but actually operates as a public client (no secret, uses PKCE).
Treat clients without a stored clientSecret as public clients, regardless of tokenEndpointAuthMethod:
const isPublicClient =
client.tokenEndpointAuthMethod === 'none' ||
!client.clientSecret; // ← Key addition
if (isPublicClient) {
// PKCE validation only, no client_secret required
} else {
// Validate client_secret
}- Dev works, prod doesn't? → Check for
Response.json()/Response.redirect() - Routes missing from build? → Check page exports, look at
app-paths-manifest.json - Prisma engine not found? → Add
binaryTargetsto schema - OAuth 401 on token exchange? → Log
tokenEndpointAuthMethodandclientSecretpresence