Error Handling
On Error is the only life-cycle event that is not always executed on each request, but only when an error is thrown in any other life-cycle at least once.
Designed to capture and resolve an unexpected error, its recommended to use on Error in the following situation:
- To provide custom error message
- Fail safe or an error handler or retrying a request
- Logging and analytic
Example
Elysia catches all the errors thrown in the handler, classifies the error code, and pipes them to onError
middleware.
import { Elysia } from 'elysia'
new Elysia()
.onError(({ code, error }) => {
return new Response(error.toString())
})
.get('/', () => {
throw new Error('Server is during maintenance')
return 'unreachable'
})
With onError
we can catch and transform the error into a custom error message.
TIP
It's important that onError
must be called before the handler we want to apply it to.
For example, returning custom 404 messages:
import { Elysia, NotFoundError } from 'elysia'
new Elysia()
.onError(({ code, error, set }) => {
if (code === 'NOT_FOUND') {
set.status = 404
return 'Not Found :('
}
})
.post('/', () => {
throw new NotFoundError()
})
.listen(3000)
Context
onError
Context is extends from Context
with additional properties of the following:
- error: Error object thrown
- code: Error Code
Error Code
Elysia error code consists of:
- NOT_FOUND
- INTERNAL_SERVER_ERROR
- VALIDATION
- PARSE
- UNKNOWN
By default, the thrown error code is unknown
.
TIP
If no error response is returned, the error will be returned using error.name
.
Custom Error
Elysia supports custom error both in the type-level and implementation level.
To provide a custom error code, we can use Elysia.error
to add a custom error code, helping us to easily classify and narrow down the error type for full type safety with auto-complete as the following:
import { Elysia } from 'elysia'
class MyError extends Error {
constructor(public message: string) {
super(message)
}
}
new Elysia()
.error({
MyError
})
.onError(({ code, error }) => {
switch (code) {
// With auto-completion
case 'MyError':
// With type narrowing
// Hover to see error is typed as `CustomError`
return error
}
})
.get('/', () => {
throw new MyError('Hello Error')
})
Properties of error
code is based on the properties of error
, the said properties will be used to classify the error code.
Local Error
Same as others life-cycle, we provide an error into an scope using guard:
import { Elysia } from 'elysia'
new Elysia()
.get('/', () => 'Hello', {
beforeHandle({ set, request: { headers } }) {
if (!isSignIn(headers)) {
set.status = 401
throw new Error('Unauthorized')
}
},
error({ error }) {
return 'Handled'
}
})
.listen(3000)