Comprehensive error classes with detailed metadata for different failure scenarios, providing rich context for debugging and error recovery.
The base error class for all Got-related request failures.
/**
* Base error class for request failures
* Contains detailed request/response metadata and timing information
*/
class RequestError<T = unknown> extends Error {
/**
* Error name identifier
*/
readonly name: "RequestError";
/**
* Error code (e.g., ECONNREFUSED, ETIMEDOUT)
*/
readonly code: string;
/**
* Request options that were used
*/
readonly options: Options;
/**
* Response object if available
*/
readonly response?: Response<T>;
/**
* Request object
*/
readonly request?: Request;
/**
* Request timing information
*/
readonly timings?: Timings;
/**
* Original input that caused the error
*/
input?: string;
/**
* Create a new RequestError
* @param message - Error message
* @param error - Original error object
* @param self - Request or Options object
*/
constructor(message: string, error: Partial<Error & {code?: string}>, self: Request | Options);
}Usage Examples:
import got, { RequestError } from "got";
try {
const response = await got("https://nonexistent.example.com");
} catch (error) {
if (error instanceof RequestError) {
console.log("Error code:", error.code); // e.g., "ENOTFOUND"
console.log("Request URL:", error.options.url);
console.log("Request method:", error.options.method);
if (error.timings) {
console.log("Request duration:", error.timings.phases?.total);
}
}
}Error thrown for HTTP responses with non-2xx status codes (when throwHttpErrors is true).
/**
* Error for HTTP responses with error status codes
* Always includes response object with status code and body
*/
class HTTPError<T = any> extends RequestError<T> {
/**
* Error name identifier
*/
readonly name: "HTTPError";
/**
* Error code
*/
readonly code: "ERR_NON_2XX_3XX_RESPONSE";
/**
* HTTP response object (always present)
*/
readonly response: Response<T>;
/**
* Request object (always present)
*/
readonly request: Request;
/**
* Request timings (always present)
*/
readonly timings: Timings;
/**
* Create a new HTTPError
* @param response - HTTP response object
*/
constructor(response: PlainResponse);
}Usage Examples:
import got, { HTTPError } from "got";
try {
const response = await got("https://api.example.com/users/999");
} catch (error) {
if (error instanceof HTTPError) {
console.log("HTTP Status:", error.response.statusCode); // 404
console.log("Status Message:", error.response.statusMessage); // "Not Found"
console.log("Response Body:", error.response.body);
console.log("Request URL:", error.response.requestUrl);
// Handle specific status codes
switch (error.response.statusCode) {
case 404:
console.log("Resource not found");
break;
case 401:
console.log("Authentication required");
break;
case 429:
console.log("Rate limited");
break;
default:
console.log("HTTP error:", error.response.statusCode);
}
}
}Error thrown when the request exceeds the maximum number of allowed redirects.
/**
* Error for excessive redirects
* Thrown when request exceeds maxRedirects limit
*/
class MaxRedirectsError extends RequestError {
/**
* Error name identifier
*/
readonly name: "MaxRedirectsError";
/**
* Error code
*/
readonly code: "ERR_TOO_MANY_REDIRECTS";
/**
* Final response object (always present)
*/
readonly response: Response;
/**
* Request object (always present)
*/
readonly request: Request;
/**
* Request timings (always present)
*/
readonly timings: Timings;
/**
* Create a new MaxRedirectsError
* @param request - Request object
*/
constructor(request: Request);
}Usage Examples:
import got, { MaxRedirectsError } from "got";
try {
const response = await got("https://example.com/infinite-redirect", {
maxRedirects: 5
});
} catch (error) {
if (error instanceof MaxRedirectsError) {
console.log("Too many redirects");
console.log("Final URL:", error.response.url);
console.log("Redirect chain:", error.response.redirectUrls);
console.log("Max redirects allowed:", error.request.options.maxRedirects);
}
}Error thrown when various timeout limits are exceeded during the request.
/**
* Error for request timeouts
* Thrown when any timeout limit is exceeded
*/
class TimeoutError extends RequestError {
/**
* Error name identifier
*/
readonly name: "TimeoutError";
/**
* Error code indicating timeout type
*/
readonly code: string; // "ETIMEDOUT", "ESOCKETTIMEDOUT", etc.
/**
* Which timeout was exceeded
*/
readonly timings: Timings;
/**
* Timeout event that triggered the error
*/
readonly event: string;
/**
* Create a new TimeoutError
* @param error - Timeout error details
* @param timings - Request timing information
* @param request - Request object
*/
constructor(error: TimeoutErrorOptions, timings: Timings, request: Request);
}
interface TimeoutErrorOptions {
event: string;
threshold: number;
}Usage Examples:
import got, { TimeoutError } from "got";
try {
const response = await got("https://slow-api.example.com", {
timeout: {
request: 5000, // 5 second overall limit
response: 3000 // 3 second response limit
}
});
} catch (error) {
if (error instanceof TimeoutError) {
console.log("Timeout event:", error.event); // "request", "response", etc.
console.log("Timeout code:", error.code);
if (error.timings) {
console.log("Time elapsed:", error.timings.phases?.total);
}
}
}Other specific error types for various failure scenarios.
/**
* Error for cache-related failures
*/
class CacheError extends RequestError {
readonly name: "CacheError";
readonly code: "ERR_CACHE_ACCESS";
}
/**
* Error for request body upload failures
*/
class UploadError extends RequestError {
readonly name: "UploadError";
readonly code: "ERR_UPLOAD";
}
/**
* Error for response body reading failures
*/
class ReadError extends RequestError {
readonly name: "ReadError";
readonly code: "ERR_READING_RESPONSE_STREAM";
}
/**
* Error to force request retries
*/
class RetryError extends RequestError {
readonly name: "RetryError";
readonly code: "ERR_RETRYING";
}
/**
* Error for aborted requests (via AbortController)
*/
class AbortError extends RequestError {
readonly name: "AbortError";
readonly code: "ERR_ABORTED";
}
/**
* Error for response body parsing failures
*/
class ParseError extends RequestError {
readonly name: "ParseError";
readonly code: "ERR_BODY_PARSE_FAILURE";
}
/**
* Error for canceled promises
*/
class CancelError extends RequestError {
readonly name: "CancelError";
readonly code: "ERR_CANCELED";
/**
* Whether the promise is canceled
*/
get isCanceled(): boolean;
}Common patterns for handling different types of errors.
Basic Error Handling:
import got, { RequestError, HTTPError, TimeoutError } from "got";
async function fetchData(url: string) {
try {
const response = await got(url).json();
return response;
} catch (error) {
if (error instanceof HTTPError) {
// Handle HTTP errors (4xx, 5xx status codes)
switch (error.response.statusCode) {
case 404:
throw new Error("Resource not found");
case 429:
throw new Error("Rate limited - try again later");
case 500:
throw new Error("Server error - try again later");
default:
throw new Error(`HTTP error: ${error.response.statusCode}`);
}
} else if (error instanceof TimeoutError) {
// Handle timeout errors
throw new Error("Request timed out - server is slow");
} else if (error instanceof RequestError) {
// Handle other request errors (network, DNS, etc.)
switch (error.code) {
case "ENOTFOUND":
throw new Error("DNS lookup failed - check URL");
case "ECONNREFUSED":
throw new Error("Connection refused - server may be down");
case "ECONNRESET":
throw new Error("Connection reset - network issue");
default:
throw new Error(`Network error: ${error.code}`);
}
} else {
// Handle unexpected errors
throw error;
}
}
}Retry with Error Handling:
import got, { HTTPError, RequestError } from "got";
async function fetchWithRetry(url: string, maxRetries: number = 3) {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await got(url, {
timeout: { request: 10000 },
retry: { limit: 0 } // Handle retries manually
});
return response;
} catch (error) {
lastError = error;
if (error instanceof HTTPError) {
// Don't retry client errors (4xx)
if (error.response.statusCode >= 400 && error.response.statusCode < 500) {
throw error;
}
} else if (error instanceof RequestError) {
// Don't retry permanent failures
if (["ENOTFOUND", "EINVAL"].includes(error.code)) {
throw error;
}
}
// Wait before retry (exponential backoff)
if (attempt < maxRetries) {
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError!;
}Graceful Error Handling:
import got, { RequestError } from "got";
async function safeRequest(url: string) {
try {
const response = await got(url, {
throwHttpErrors: false, // Don't throw on HTTP errors
timeout: { request: 5000 },
retry: { limit: 2 }
});
return {
success: response.statusCode >= 200 && response.statusCode < 300,
status: response.statusCode,
body: response.body,
error: null
};
} catch (error) {
return {
success: false,
status: 0,
body: null,
error: error instanceof RequestError ? {
code: error.code,
message: error.message,
type: error.constructor.name
} : {
code: "UNKNOWN",
message: error.message,
type: "Unknown"
}
};
}
}All Got errors include rich metadata for debugging and error recovery:
| Property | Description | Availability |
|---|---|---|
code | Error code (ENOTFOUND, ETIMEDOUT, etc.) | All errors |
options | Request options used | All errors |
request | Request object | Most errors |
response | Response object | HTTP errors |
timings | Request timing data | Most errors |
retryCount | Number of retries attempted | After retries |
redirectUrls | Redirect chain | After redirects |