discordjs/discord.js · error · HTTPError

HTTPError(status, res.statusText, method, url, requestData)

Error message

HTTPError(status, res.statusText, method, url, requestData)

What it means

handleErrors() in Shared.ts throws an HTTPError when Discord returns a 4xx/5xx status that could not be recovered from: for 5xx, either a retry backoff could not be computed (normalizeRetryBackoff returned null, e.g. rejectOnRateLimit/retryBackoff callback rejected) or all configured retries were exhausted. The error carries the status code, statusText, method, URL, and request body so the caller can inspect what failed.

Source

Thrown at packages/rest/src/lib/handlers/Shared.ts:170

	method: string,
	url: string,
	requestData: HandlerRequestData,
	retries: number,
	routeId: RouteData,
) {
	const status = res.status;
	if (status >= 500 && status < 600) {
		// Retry the specified number of times for possible server side issues
		if (retries !== manager.options.retries) {
			const backoff = normalizeRetryBackoff(
				manager.options.retryBackoff,
				routeId.bucketRoute,
				status,
				retries,
				requestData.body,
			);
			if (backoff === null) {
				throw new HTTPError(status, res.statusText, method, url, requestData);
			}

			if (backoff > 0) {
				await sleep(backoff);
			}

			return null;
		}

		// We are out of retries, throw an error
		throw new HTTPError(status, res.statusText, method, url, requestData);
	} else {
		// Handle possible malformed requests
		if (status >= 400 && status < 500) {
			// The request will not succeed for some reason, parse the error returned from the api
			const data = (await parseResponse(res)) as DiscordErrorData | OAuthErrorData;
			const isDiscordError = 'code' in data;

View on GitHub (pinned to a81ed8a306)

Solutions

  1. Read error.status and the parsed error body (error.rawError / error.code) to identify the root cause — 5xx means retry later, 4xx means fix the request.
  2. For 5xx, wrap requests in retry logic with exponential backoff and consider raising RESTOptions.retries (default 3).
  3. For 4xx, fix the request: validate the JSON body, check route parameters exist, and ensure the bot token/permissions are valid for 401/403.
  4. Listen to RESTEvents.Response / use the error's method, url, and requestData fields to log the exact failing request for diagnosis.
  5. Check the Discord status page (discordstatus.com) when seeing clusters of 5xx errors.

Example fix

// before
const user = await rest.get(Routes.user(id)); // throws HTTPError on transient 502
// after
try {
  const user = await rest.get(Routes.user(id));
} catch (error) {
  if (error instanceof HTTPError && error.status >= 500) {
    await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
    return retry();
  }
  throw error;
}
Defensive patterns

Strategy: retry

Validate before calling

// Validate request shape before sending to avoid 4xx HTTPErrors
function assertValidUserId(id: string) {
  if (!/^\d{17,20}$/.test(id)) throw new TypeError(`Invalid snowflake id: ${id}`);
}

Type guard

import { HTTPError } from '@discordjs/rest';
const isHTTPError = (e: unknown): e is HTTPError => e instanceof HTTPError;
const isServerError = (e: unknown): e is HTTPError => isHTTPError(e) && e.status >= 500;

Try / catch

async function withRetry<T>(fn: () => Promise<T>, attempts = 3): Promise<T> {
  try {
    return await fn();
  } catch (error) {
    if (isHTTPError(error) && error.status >= 500 && attempts > 0) {
      await new Promise((r) => setTimeout(r, 1000 * 2 ** (3 - attempts)));
      return withRetry(fn, attempts - 1);
    }
    throw error;
  }
}

Prevention

When it happens

Trigger: Discord returning 500/502/503/504 on every attempt until manager.options.retries (default 3) is exhausted; a 5xx response where the retryBackoff function (or rejectOnRateLimit-style callback) returns/rejects such that normalizeRetryBackoff yields null; any 4xx (400/401/403/404) which is never retried and immediately surfaces as an HTTPError.

Common situations: Discord API incidents/outages causing sustained 5xx responses; malformed request payloads producing 400; revoked or lacking permissions producing 403; deleted resources producing 404; aggressive custom retryBackoff configuration that cancels retries.

Related errors


AI-assisted analysis of discordjs/discord.js@a81ed8a306 (2026-08-30). Data as JSON: /api/errors/d0fbb8ff31f3214b. Report an issue: GitHub.