or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

content-parsing.mddecoration.mderror-handling.mdhooks.mdindex.mdplugins.mdrouting.mdschema.mdserver-lifecycle.mdtesting.md
tile.json

error-handling.mddocs/

Error Handling

Comprehensive error handling system with custom error handlers and built-in error types.

Capabilities

Error Handlers

Set custom error handlers for application-wide error processing.

/**
 * Set custom error handler for all unhandled errors
 * @param handler - Error handling function
 * @returns FastifyInstance for method chaining
 */
setErrorHandler(handler: (
  error: FastifyError,
  request: FastifyRequest,
  reply: FastifyReply
) => void | Promise<void>): FastifyInstance;

Usage Examples:

// Basic error handler
fastify.setErrorHandler((error, request, reply) => {
  // Log error
  request.log.error(error);
  
  // Send appropriate response
  if (error.statusCode) {
    reply.status(error.statusCode).send({
      error: error.name,
      message: error.message
    });
  } else {
    reply.status(500).send({
      error: 'Internal Server Error',
      message: 'Something went wrong'
    });
  }
});

// Async error handler with custom logic
fastify.setErrorHandler(async (error, request, reply) => {
  // Record error in monitoring system
  await errorTracker.recordError(error, {
    requestId: request.id,
    userId: request.user?.id,
    route: request.routerPath
  });
  
  // Handle different error types
  if (error.code === 'FST_ERR_VALIDATION') {
    reply.status(400).send({
      error: 'Validation Error',
      details: error.validation
    });
  } else if (error.statusCode === 404) {
    reply.status(404).send({
      error: 'Not Found',
      message: 'The requested resource was not found'
    });
  } else {
    reply.status(500).send({
      error: 'Internal Server Error',
      message: process.env.NODE_ENV === 'production' 
        ? 'Something went wrong' 
        : error.message
    });
  }
});

Not Found Handlers

Handle 404 errors with custom logic.

/**
 * Set custom handler for 404 Not Found errors
 * @param handler - Not found handling function
 * @returns FastifyInstance for method chaining
 */
setNotFoundHandler(handler: (
  request: FastifyRequest,
  reply: FastifyReply
) => void | Promise<void>): FastifyInstance;

/**
 * Set not found handler with options
 * @param options - Handler configuration options
 * @param handler - Not found handling function
 * @returns FastifyInstance for method chaining
 */
setNotFoundHandler(
  options: {
    preValidation?: Function | Function[];
    preHandler?: Function | Function[];
  },
  handler: (request: FastifyRequest, reply: FastifyReply) => void | Promise<void>
): FastifyInstance;

Usage Examples:

// Basic 404 handler
fastify.setNotFoundHandler((request, reply) => {
  reply.code(404).send({
    error: 'Not Found',
    message: `Route ${request.method} ${request.url} not found`,
    statusCode: 404
  });
});

// 404 handler with custom logic
fastify.setNotFoundHandler(async (request, reply) => {
  // Log 404s for analytics
  request.log.warn(`404: ${request.method} ${request.url}`);
  
  // Try to suggest similar routes
  const suggestions = await findSimilarRoutes(request.url);
  
  reply.code(404).send({
    error: 'Not Found',
    message: `Route ${request.url} not found`,
    suggestions: suggestions.length > 0 ? suggestions : undefined
  });
});

// 404 handler with preprocessing
fastify.setNotFoundHandler({
  preValidation: (request, reply, done) => {
    // Rate limit 404 requests
    const key = `404_${request.ip}`;
    rateLimiter.check(key, (err, allowed) => {
      if (!allowed) {
        reply.code(429).send({ error: 'Too Many Requests' });
        return;
      }
      done();
    });
  }
}, (request, reply) => {
  reply.code(404).send({ error: 'Not Found' });
});

FastifyError Types

Understanding Fastify's built-in error types and creating custom errors.

/**
 * Base Fastify error interface
 */
interface FastifyError extends Error {
  name: string;
  message: string;
  code: string;
  statusCode?: number;
  validation?: FastifySchemaValidationError[];
  validationContext?: string;
}

Common Error Codes:

// Built-in Fastify error codes
const errorCodes = {
  FST_ERR_VALIDATION: 'Request validation failed',
  FST_ERR_INVALID_URL: 'Invalid URL',
  FST_ERR_ROUTE_ALREADY_EXISTS: 'Route already exists',
  FST_ERR_PLUGIN_NOT_VALID: 'Plugin is not valid',
  FST_ERR_HOOK_INVALID_TYPE: 'Hook type is invalid',
  FST_ERR_HOOK_INVALID_HANDLER: 'Hook handler is invalid',
  FST_ERR_INSTANCE_ALREADY_LISTENING: 'Instance is already listening',
  // ... many more
};

// Access error codes
const { FST_ERR_VALIDATION } = require('fastify').errorCodes;

Custom Error Creation

Create and throw custom errors with proper status codes.

// Using @fastify/error for custom errors
const createError = require('@fastify/error');

// Define custom error types
const ValidationError = createError('VALIDATION_ERROR', 'Validation failed: %s', 400);
const AuthorizationError = createError('AUTHORIZATION_ERROR', 'Access denied: %s', 403);
const NotFoundError = createError('NOT_FOUND_ERROR', 'Resource not found: %s', 404);

// Use in route handlers
fastify.get('/users/:id', async (request, reply) => {
  const user = await findUser(request.params.id);
  if (!user) {
    throw new NotFoundError('User not found');
  }
  return user;
});

// Use in hooks
fastify.addHook('preHandler', async (request, reply) => {
  if (!request.user) {
    throw new AuthorizationError('Authentication required');
  }
  
  if (!request.user.active) {
    throw new AuthorizationError('Account is disabled');
  }
});

Error Handler Scope

Error handlers can be scoped to specific plugin contexts.

// Global error handler
fastify.setErrorHandler((error, request, reply) => {
  request.log.error(error, 'Global error handler');
  reply.status(500).send({ error: 'Internal Server Error' });
});

// Plugin-scoped error handler
await fastify.register(async function (fastify) {
  // This error handler only applies to routes in this plugin
  fastify.setErrorHandler((error, request, reply) => {
    request.log.error(error, 'Plugin error handler');
    
    if (error.code === 'PLUGIN_SPECIFIC_ERROR') {
      reply.status(422).send({ error: 'Plugin specific error' });
    } else {
      // Forward to parent error handler
      throw error;
    }
  });
  
  fastify.get('/plugin-route', handler);
});

Validation Error Handling

Handle schema validation errors specifically.

// Custom validation error handling
fastify.setErrorHandler((error, request, reply) => {
  if (error.code === 'FST_ERR_VALIDATION') {
    const validationErrors = error.validation.map(err => ({
      field: err.instancePath || err.schemaPath,
      message: err.message,
      value: err.data
    }));
    
    reply.status(400).send({
      error: 'Validation Error',
      message: 'Request validation failed',
      details: validationErrors
    });
    return;
  }
  
  // Handle other errors
  reply.status(error.statusCode || 500).send({
    error: error.name || 'Error',
    message: error.message
  });
});

// Using attachValidation for manual handling
fastify.post('/users', {
  attachValidation: true,
  schema: { body: userSchema }
}, async (request, reply) => {
  if (request.validationError) {
    // Custom validation error response
    reply.status(400).send({
      success: false,
      error: 'Invalid user data',
      fields: request.validationError.validation.map(err => ({
        name: err.instancePath.replace('/', ''),
        message: err.message
      }))
    });
    return;
  }
  
  const user = await createUser(request.body);
  reply.status(201).send({ success: true, user });
});

Error Context and Logging

Enhance error handling with context and structured logging.

// Enhanced error handler with context
fastify.setErrorHandler(async (error, request, reply) => {
  const errorContext = {
    requestId: request.id,
    method: request.method,
    url: request.url,
    userAgent: request.headers['user-agent'],
    ip: request.ip,
    userId: request.user?.id,
    timestamp: new Date().toISOString(),
    stack: error.stack
  };
  
  // Structured error logging
  request.log.error({
    err: error,
    context: errorContext
  }, 'Request error occurred');
  
  // Send to external error tracking
  if (process.env.NODE_ENV === 'production') {
    await errorTracker.capture(error, errorContext);
  }
  
  // Send appropriate response
  const isDevelopment = process.env.NODE_ENV === 'development';
  reply.status(error.statusCode || 500).send({
    error: error.name || 'Error',
    message: error.message,
    ...(isDevelopment && { stack: error.stack }),
    requestId: request.id
  });
});

Framework Error Handling

Handle framework-level errors that occur outside normal request processing.

// Framework error handler (set in options)
const fastify = require('fastify')({
  frameworkErrors: (error, request, reply) => {
    // Handle framework-level errors (e.g., malformed JSON)
    if (error.type === 'entity.parse.failed') {
      reply.status(400).send({
        error: 'Bad Request',
        message: 'Invalid JSON in request body'
      });
    } else {
      reply.status(500).send({
        error: 'Framework Error',
        message: 'A framework-level error occurred'
      });
    }
  }
});