
Keep internal error details on the server
Client error responses keep the information needed to understand a refusal or correct an input, while internal context is filtered before serialization. Wildo applies a shared rule instead of asking every endpoint to decide what to expose.
Operators retain diagnostic information; clients receive a structured response with a message reference and support correlation ID.
Example — Explain a failed save safely
A form can receive field-level validation feedback. A database failure follows a different path: its internal context is removed from the client response, while the support identifier helps locate the server-side event.
For engineers
Know which context may cross the boundary
sanitizeErrorForClient() treats validation, conflict and rate-limit context as candidates for an explicit key allow-list. Authentication uses a narrower list, including specific lockout feedback. Other families remove their context. This selected source excerpt shows the default branch:
// All other types (AUTHZ, INTERNAL, DATABASE, etc.): strip context entirely
const { context, ...rest } = wildoError;
return rest as WildoError_Backend;
The sanitizer removes context; the response serializer separately chooses public fields and omits the backend stack. Do not interpret the returned backend-shaped object as a response DTO to send wholesale.
Follow serialization, not just the filter
This excerpt selects fields from the actual ErrorHandlerService response assembly; other response metadata is omitted:
const response: ErrorResponse = {
error: {
type: saasError.type,
message: saasError.customMessageReference,
...(typeof sanitizedError.context?.code === 'string' && { code: sanitizedError.context.code }),
correlationId: saasError.correlationId ?? getCurrentCorrelationId(),
...(sanitizedError.context && { details: sanitizedError.context }),
...(validationErrors && { validationErrors }),
// Other selected response metadata remains in the implementation.
}
};
This is a selected implementation excerpt, not a complete typed replacement. Validation issues are extracted before context filtering into a separate field map. An allowed stable code is promoted to error.code, allowing a client to branch on a declared identifier instead of parsing translated text.
Author safe details at their source
The allow-list checks key names, not the sensitivity of arbitrary values placed under them. Keep driver messages, stacks and secret material out of public fields; use a named shared code when clients need a specific branch.
Response filtering and authorization are different contracts. A filter cannot make two responses indistinguishable if upstream code selects different statuses or exposes different existence information. The response also retains selected metadata such as operation and initiator information; it is not an anonymous two-field envelope. Review the concrete route’s response when making a confidentiality claim.