TypeScript 97.5%
SQL 1.4%
Python 0.8%
1export const ERROR_CODES = [2 "INVALID_API_KEY",3 "EMAIL_NOT_VERIFIED",4 "RATE_LIMITED",5 "CONCURRENCY_LIMIT",6 "INVALID_REQUEST",7 "URL_NOT_ALLOWED",8 "TARGET_TIMEOUT",9 "TARGET_BLOCKED",10 "TARGET_UNAVAILABLE",11 "PROVIDER_UNAVAILABLE",12 "NETWORK_UNAVAILABLE",13 "BROWSER_UNAVAILABLE",14 "BROWSER_TIMEOUT",15 "RESPONSE_TOO_LARGE",16 "TOO_MANY_REDIRECTS",17 "INSUFFICIENT_CREDITS",18 "USAGE_LIMIT_REACHED",19 "SESSION_NOT_FOUND",20 "SESSION_EXPIRED",21 "CRAWL_NOT_FOUND",22 "CRAWL_LIMIT_REACHED",23 "NOT_FOUND",24 "FORBIDDEN",25 "INTERNAL_ERROR",26] as const;2728export type ErrorCode = (typeof ERROR_CODES)[number];2930export const ERROR_HTTP_STATUS: Record<ErrorCode, number> = {31 INVALID_API_KEY: 401,32 EMAIL_NOT_VERIFIED: 403,33 RATE_LIMITED: 429,34 CONCURRENCY_LIMIT: 429,35 INVALID_REQUEST: 400,36 URL_NOT_ALLOWED: 400,37 TARGET_TIMEOUT: 504,38 TARGET_BLOCKED: 502,39 TARGET_UNAVAILABLE: 502,40 PROVIDER_UNAVAILABLE: 503,41 NETWORK_UNAVAILABLE: 400,42 BROWSER_UNAVAILABLE: 400,43 BROWSER_TIMEOUT: 504,44 RESPONSE_TOO_LARGE: 502,45 TOO_MANY_REDIRECTS: 502,46 INSUFFICIENT_CREDITS: 402,47 USAGE_LIMIT_REACHED: 402,48 SESSION_NOT_FOUND: 404,49 SESSION_EXPIRED: 410,50 CRAWL_NOT_FOUND: 404,51 CRAWL_LIMIT_REACHED: 429,52 NOT_FOUND: 404,53 FORBIDDEN: 403,54 INTERNAL_ERROR: 500,55};5657export const ERROR_MESSAGES: Record<ErrorCode, string> = {58 INVALID_API_KEY: "The API key is missing, malformed, revoked or expired.",59 EMAIL_NOT_VERIFIED: "Verify your email address before using the production API.",60 RATE_LIMITED: "Too many requests. Slow down and retry after the indicated delay.",61 CONCURRENCY_LIMIT: "Concurrent request limit reached for your organization.",62 INVALID_REQUEST: "The request body is invalid.",63 URL_NOT_ALLOWED: "The target URL is not allowed.",64 TARGET_TIMEOUT: "The target did not respond in time.",65 TARGET_BLOCKED: "The target blocked every route we tried.",66 TARGET_UNAVAILABLE: "The target could not be reached.",67 PROVIDER_UNAVAILABLE: "No network route is currently available for this request.",68 NETWORK_UNAVAILABLE: "The requested network class is not available right now.",69 BROWSER_UNAVAILABLE: "The managed browser is disabled or temporarily unavailable.",70 BROWSER_TIMEOUT: "The browser did not finish in time.",71 RESPONSE_TOO_LARGE: "The response exceeded the maximum allowed size.",72 TOO_MANY_REDIRECTS: "The target redirected too many times.",73 INSUFFICIENT_CREDITS: "Your account has no remaining credits.",74 USAGE_LIMIT_REACHED: "A spending or usage limit configured on this project was reached.",75 SESSION_NOT_FOUND: "The session does not exist.",76 SESSION_EXPIRED: "The session has expired.",77 CRAWL_NOT_FOUND: "The crawl job does not exist.",78 CRAWL_LIMIT_REACHED: "Too many crawl jobs are running for your organization.",79 NOT_FOUND: "Resource not found.",80 FORBIDDEN: "You do not have access to this resource.",81 INTERNAL_ERROR: "An internal error occurred.",82};8384export class FetchaError extends Error {85 readonly code: ErrorCode;86 readonly status: number;87 readonly details?: Record<string, unknown>;88 readonly requestId?: string;8990 constructor(91 code: ErrorCode,92 message?: string,93 opts: { details?: Record<string, unknown>; requestId?: string; cause?: unknown } = {},94 ) {95 super(message ?? ERROR_MESSAGES[code], { cause: opts.cause });96 this.name = "FetchaError";97 this.code = code;98 this.status = ERROR_HTTP_STATUS[code];99 this.details = opts.details;100 this.requestId = opts.requestId;101 }102103 toJSON(requestId?: string) {104 return {105 error: {106 code: this.code,107 message: this.message,108 request_id: requestId ?? this.requestId ?? null,109 ...(this.details ? { details: this.details } : {}),110 },111 };112 }113}114115export function isFetchaError(e: unknown): e is FetchaError {116 return e instanceof FetchaError || (typeof e === "object" && e !== null && (e as { name?: string }).name === "FetchaError");117}118