Skip to content

Instantly share code, notes, and snippets.

@disintegrator
Created January 7, 2025 23:30
Show Gist options
  • Save disintegrator/a39718110df68cc7d61df219e6237baf to your computer and use it in GitHub Desktop.
Save disintegrator/a39718110df68cc7d61df219e6237baf to your computer and use it in GitHub Desktop.
Cross-platform fetch error classification
/**
* Uses various heurisitics to determine if an error is a connection error.
*/
export function isConnectionError(err: unknown): boolean {
if (typeof err !== "object" || err == null) {
return false;
}
// Covers fetch in Deno as well
const isBrowserErr =
err instanceof TypeError &&
err.message.toLowerCase().startsWith("failed to fetch");
const isNodeErr =
err instanceof TypeError &&
err.message.toLowerCase().startsWith("fetch failed");
const isBunErr = "name" in err && err.name === "ConnectionError";
const isGenericErr =
"code" in err &&
typeof err.code === "string" &&
err.code.toLowerCase() === "econnreset";
return isBrowserErr || isNodeErr || isGenericErr || isBunErr;
}
/**
* Uses various heurisitics to determine if an error is a timeout error.
*/
export function isTimeoutError(err: unknown): boolean {
if (typeof err !== "object" || err == null) {
return false;
}
// Fetch in browser, Node.js, Bun, Deno
const isNative = "name" in err && err.name === "TimeoutError";
const isLegacyNative = "code" in err && err.code === 23;
// Node.js HTTP client and Axios
const isGenericErr =
"code" in err &&
typeof err.code === "string" &&
err.code.toLowerCase() === "econnaborted";
return isNative || isLegacyNative || isGenericErr;
}
/**
* Uses various heurisitics to determine if an error is a abort error.
*/
export function isAbortError(err: unknown): boolean {
if (typeof err !== "object" || err == null) {
return false;
}
// Fetch in browser, Node.js, Bun, Deno
const isNative = "name" in err && err.name === "AbortError";
const isLegacyNative = "code" in err && err.code === 20;
// Node.js HTTP client and Axios
const isGenericErr =
"code" in err &&
typeof err.code === "string" &&
err.code.toLowerCase() === "econnaborted";
return isNative || isLegacyNative || isGenericErr;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment