Skip to content

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.

typescript
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:

typescript
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:

typescript
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:

typescript
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)