Skip to main content
An action that fails throws an error. There are three kinds, all exported by chapterjs, and you can tell them apart with instanceof.
What happens when your function throws without catching is in Answering for commands and in Events for events: the bot never stops, you get the error in your terminal with the file and the line.

DiscordApiError

Discord answered a request with an error. It is thrown when Discord refuses what the bot asked: a missing permission, something that no longer exists, a value it does not accept. The request was received and understood; retrying it gives the same answer until something changes.
'DiscordApiError'
required
What instanceof tells, as text.
string
required
What happened, with the reason Discord gave and the fields it refused: Discord refused POST /channels/{channel.id}/messages: Missing Permissions (50013)., then what it means in plain words for the codes a bot meets most (a missing permission, something deleted, private messages closed), and one line per refused field when there are some.
number
required
The HTTP status of the response (403, 404…).
number
required
The JSON error code of Discord (50013 for “Missing Permissions”…), or 0 when the response had none.
readonly DiscordFieldError[]
required
The fields of the request Discord refused, when it says which.
'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
required
The HTTP method of the request that failed.
string
required
The path of the endpoint as written in the documentation.

Codes you will meet

Test error.code, never error.message: the text may change, the code does not. The full list is in the Discord documentation.

DiscordFieldError

One problem Discord found in a field of the request.
string
required
Where the problem is: embeds[0].title, or empty ('') for the whole request.
string
required
The kind of problem, as Discord names it (BASE_TYPE_MAX_LENGTH).
string
required
What is wrong, in English.
Discord documentation

DiscordUnavailableError

A request could not reach Discord, or Discord kept failing. It is thrown when there is no answer to get: no internet connection, an outage of Discord, a server error that persisted. The bot already retried before throwing it; retrying later may work.
'DiscordUnavailableError'
required
What instanceof tells, as text.
string
required
Discord could not be reached for GET /guilds/{guild.id}. Check your internet connection and https://discordstatus.com, then try again.
'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
required
The HTTP method of the request that failed.
string
required
The path of the endpoint as written in the documentation.
unknown
The underlying error, when Node gave one.

InvalidTokenError

The bot token was refused: no request can succeed until it is fixed. It is thrown by every request once Discord refused the token: the bot stops sending anything, so a wrong token never floods Discord. Nothing in your code can fix it; chapterjs dev checks the token before connecting, so you normally see it there (see Troubleshooting).
'InvalidTokenError'
required
What instanceof tells, as text.
string
required
Discord refused the bot token. Copy it again from the Developer Portal (your application → Bot → Reset Token) into BOT_TOKEN in your .env file.

Catching

Catch only what you expect, and let the rest through: an error you don’t handle is reported with its file and line, which is what you want for a bug.
src/commands/kick.ts

What the person sees

When run throws and you did not catch, the person who used the command gets a short, private answer, never the technical details:
When the error is a DiscordApiError with code 50013 or 50001, the answer says what is missing instead:
The error itself, with its file and line, goes to your terminal. See Answering. Both phrases can be translated in the language files of the project: see What the bot answers by itself.

What never throws

Rate limits are not errors: when the bot goes too fast, requests wait for their turn and then succeed. A temporary failure of Discord is retried before anything is thrown.