Skip to main content

Overview

Result Handlers are responsible for transforming endpoint outputs and errors into HTTP responses. They ensure consistent response formatting across your API and handle both successful results and errors. Every endpoint uses a Result Handler, either the default one or a custom implementation.

Result Handler Structure

A Result Handler defines:
  • Positive response schema: How successful outputs are formatted
  • Negative response schema: How errors are formatted
  • Handler function: Logic that sends the actual HTTP response

The Default Result Handler

The defaultResultHandler provides a standard response format:
Status codes:
  • 200 for successful responses
  • 400 for input validation errors
  • 500 for server errors (or error’s statusCode if using createHttpError)

Creating Custom Result Handlers

Handler Function Parameters

The handler receives a discriminated union based on success or failure:
Error | null
The error if one occurred, or null on success. Use ensureHttpError() to normalize it.
FlatObject | null
The validated endpoint output on success, or null if an error occurred.
FlatObject | null
The validated input. Can be null if the error occurred before input validation.
FlatObject
Context from middlewares. May be incomplete if middleware execution was interrupted.
Request
Express request object with full access to headers, cookies, etc.
Response
Express response object for sending the response.
ActualLogger
Configured logger instance for recording errors.

Using Custom Result Handlers

Create an EndpointsFactory with your Result Handler:

Response Schemas

Static Schemas

Define a fixed response structure:

Dynamic Schemas (Lazy)

Generate the schema based on the endpoint’s output schema:
Using lazy schemas (functions) allows the documentation generator to know the exact response structure for each endpoint.

Different Status Codes

Customize status codes for different scenarios:

Non-JSON Responses

Plain Text

File Downloads

Empty Responses

For 204 No Content or redirects:

Error Handling

Normalizing Errors

Use ensureHttpError() to convert any error to an HTTP error:
Error mappings:
  • InputValidationError → 400 Bad Request
  • OutputValidationError → 500 Internal Server Error
  • HttpError → Uses error’s statusCode
  • Other errors → 500 Internal Server Error

Logging Errors

Use logServerError() helper to log server-side errors:

Public vs Private Error Messages

Control which error messages are exposed to clients:

Resource Cleanup

Clean up resources like database connections in the Result Handler:
Context may be incomplete if middleware execution was interrupted. Always check property existence using the in operator.

Common Patterns

Standard REST API

GraphQL-style Responses

API with Metadata

Array Result Handler (Legacy)

The arrayResultHandler is deprecated. It’s only provided for migrating legacy APIs. Responding with arrays prevents API evolution without breaking changes.

Best Practices

  1. Be consistent: Use one Result Handler for your entire API
  2. Use lazy schemas: Return functions from positive to get type-specific responses
  3. Handle all error types: Check for InputValidationError, OutputValidationError, and HttpError
  4. Log server errors: Use logServerError() for debugging
  5. Clean up resources: Release connections and cleanup in the handler
  6. Set proper status codes: Use ensureHttpError() to get appropriate codes
  7. Hide sensitive errors: Use getPublicErrorMessage() in production

See Also

  • Endpoints - Create endpoints that use Result Handlers
  • Error Handling - Error types and handling strategies
  • Context - Clean up context resources in handlers