--- description: How to handle errors in a Motia project globs: alwaysApply: true --- # Error Handling Guide Errors happen, but we need to handle them gracefully. Make sure you create a custom error class for your project, underneath `/src/errors/` folder. ## Good practices - Use Custom error to return errors to the client. - Anything that is not the error class, should be logged with `logger.error`. And root cause should be omitted to the client. ## Create a custom Error class Name: `/src/errors/base.error.ts` ```typescript export class BaseError extends Error { public readonly status: number public readonly code: string public readonly metadata: Record constructor( message: string, status: number = 500, code: string = 'INTERNAL_SERVER_ERROR', metadata: Record = {} ) { super(message) this.name = this.constructor.name this.status = status this.code = code this.metadata = metadata // Maintains proper stack trace for where our error was thrown Error.captureStackTrace(this, this.constructor) } toJSON() { return { error: { name: this.name, message: this.message, code: this.code, status: this.status, ...(Object.keys(this.metadata).length > 0 && { metadata: this.metadata }), }, } } } ``` Then create sub class for specific errors that are commonly thrown in your project. Name: `/src/errors/not-found.error.ts` ```typescript import { BaseError } from './base.error' export class NotFoundError extends BaseError { constructor(message: string = 'Not Found', metadata: Record = {}) { super(message, 404, 'NOT_FOUND', metadata) } } ``` ## Core Middleware Make sure you create a core middleware that will be added to ALL API Steps. File: `/src/middlewares/core.middleware.ts` ```typescript import { ApiMiddleware } from 'motia' import { ZodError } from 'zod' import { BaseError } from '../errors/base.error' export const coreMiddleware: ApiMiddleware = async (req, ctx, next) => { const logger = ctx.logger try { return await next() } catch (error: any) { if (error instanceof ZodError) { logger.error('Validation error', { error, stack: error.stack, errors: error.errors, }) return { status: 400, body: { error: 'Invalid request body', data: error.errors, }, } } else if (error instanceof BaseError) { logger.error('BaseError', { status: error.status, code: error.code, metadata: error.metadata, name: error.name, message: error.message, }) return { status: error.status, body: error.toJSON() } } logger.error('Error while performing request', { error, body: req.body, stack: error.stack, }) return { status: 500, body: { error: 'Internal Server Error' } } } } ```