3.6.8. Throwing and Handling Errors
In this guide, you'll learn how to throw errors in your Medusa application, how it affects an API route's response, and how to change the default error handler of your Medusa application.
Throw MedusaError#
When throwing an error in your API routes, middlewares, workflows, or any customization, throw a MedusaError
from the Medusa Framework.
The Medusa application's API route error handler then wraps your thrown error in a uniform object and returns it in the response.
For example:
1import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"2import { MedusaError } from "@medusajs/framework/utils"3 4export const GET = async (5 req: MedusaRequest,6 res: MedusaResponse7) => {8 if (!req.query.q) {9 throw new MedusaError(10 MedusaError.Types.INVALID_DATA,11 "The `q` query parameter is required."12 )13 }14 15 // ...16}
The MedusaError
class accepts two parameters in its constructor:
- The first is the error's type.
MedusaError
has a static propertyTypes
that you can use.Types
is an enum whose possible values are explained in the next section. - The second is the message to show in the error response.
Error Object in Response#
The error object returned in the response has three properties:
type
: The error's type.message
: The error message, if available.code
: A common snake-case code. Its values can be:invalid_request_error
for theDUPLICATE_ERROR
type.api_error
for theDB_ERROR
type.invalid_state_error
for theCONFLICT
error type.unknown_error
for any unidentified error type.- For other error types, this property won't be available unless you provide a code as a third parameter to the
MedusaError
constructor.
MedusaError Types#
Type | Description | Status Code |
---|---|---|
| Indicates a database error. |
|
| Indicates a duplicate of a record already exists. For example, when trying to create a customer whose email is registered by another customer. |
|
| Indicates an error that occurred due to incorrect arguments or other unexpected state. |
|
| Indicates a validation error. |
|
| Indicates that a user is not authorized to perform an action or access a route. |
|
| Indicates that the requested resource, such as a route or a record, isn't found. |
|
| Indicates that an operation isn't allowed. |
|
| Indicates that a request conflicts with another previous or ongoing request. The error message in this case is ignored in favor of a default message. |
|
| Indicates an error has occurred while authorizing a payment. |
|
Other error types | Any other error type results in an |
|
Override Error Handler#
The defineMiddlewares
function used to apply middlewares on routes accepts an errorHandler
in its object parameter. Use it to override the default error handler for API routes.
For example, create src/api/middlewares.ts
with the following:
7import { MedusaError } from "@medusajs/framework/utils"8 9export default defineMiddlewares({10 errorHandler: (11 error: MedusaError | any, 12 req: MedusaRequest, 13 res: MedusaResponse, 14 next: MedusaNextFunction15 ) => {16 res.status(400).json({17 error: "Something happened.",18 })19 },20})
The errorHandler
property's value is a function that accepts four parameters:
- The error thrown. Its type can be
MedusaError
or any other error type. - A request object of type
MedusaRequest
. - A response object of type
MedusaResponse
. - A function of type
MedusaNextFunction
that executes the next middleware in the stack.
This example overrides Medusa's default error handler with a handler that always returns a 400
status code with the same message.
Re-Use Default Error Handler#
In some use cases, you may not want to override the default error handler but rather perform additional actions as part of the original error handler. For example, you might want to capture the error in a third-party service like Sentry.
In those cases, you can import the default error handler from the Medusa Framework and use it in your custom error handler, along with your custom logic.
For example:
1import { 2 defineMiddlewares, 3 errorHandler, 4 MedusaNextFunction, 5 MedusaRequest, 6 MedusaResponse,7} from "@medusajs/framework/http"8import { MedusaError } from "@medusajs/framework/utils"9// assuming you have Sentry set up in your project10import * as Sentry from "@sentry/node"11 12const originalErrorHandler = errorHandler()13 14export default defineMiddlewares({15 errorHandler: (16 error: MedusaError | any, 17 req: MedusaRequest, 18 res: MedusaResponse, 19 next: MedusaNextFunction20 ) => {21 // for example, capture the error in Sentry22 Sentry.captureException(error)23 return originalErrorHandler(error, req, res, next)24 },25})
In this example, you import the errorHandler
function from the Medusa Framework. Then, you call it to get the original error handler function.
Finally, you use it in your custom error handler after performing your custom logic, such as capturing the error in Sentry.