Skip to content
Sarj Code Standards

no-exception-text-in-5xx-response

Keep caught exception messages and stacks out of returned 5xx JSON responses and Server Action results.

Why

Exception details can contain database, provider, filesystem or credential information that belongs in server-side diagnostics rather than a client response.

Fix

Return a generic public error and retain diagnostic details in server-side logs. Keep intentional public domain errors in their reviewed client-error contract.

Examples

Before — flagged Keep Server Action results independent of caught details
src/actions.ts
"use server";
const errorMessage = (error: unknown) =>
error instanceof Error ? error.message : "Unknown error";
export async function save() {
try {
await persist();
} catch (error) {
return { ok: false, message: errorMessage(error) };
}
}
After — preferred Return a stable public Server Action failure
src/actions.ts
"use server";
export async function save() {
try {
await persist();
} catch (error) {
captureException(error);
return { ok: false, message: "Could not save" };
}
}
Before — flagged Do not return a caught message as a server error
src/route.ts
function handle() {
try {
run();
} catch (error) {
return Response.json(
{ error: error instanceof Error ? error.message : "Internal server error" },
{ status: 500 },
);
}
}
After — preferred Keep internal failure details server-side
src/route.ts
function handle() {
try {
run();
} catch (error) {
return Response.json({ error: "Internal server error" }, { status: 500 });
}
}

References