/** * Check if an error is a programming error (code bug). * Programming errors should be re-thrown, not caught. */ export function isProgrammingError(error: unknown): boolean { return ( error instanceof TypeError || error instanceof ReferenceError || error instanceof SyntaxError ); } /** * Check if an error is a network error (temporary). * Network errors should return 503 (retry later). */ export function isNetworkError(error: unknown): boolean { if (!(error instanceof Error)) return false; const msg = error.message.toLowerCase(); return ( msg.includes("fetch failed") || msg.includes("network") || msg.includes("econnrefused") || msg.includes("enotfound") || msg.includes("timeout") || msg.includes("etimedout") || msg.includes("econnreset") || msg.includes("enetunreach") || msg.includes("service unavailable") ); } /** * Check if an error is an authentication error (wrong credentials). * Auth errors should NOT be retried to avoid account lockouts. */ export function isAuthError(error: unknown): boolean { if (!(error instanceof Error)) return false; const message = error.message.toLowerCase(); return ( message.includes("invalid identifier") || message.includes("invalid password") || message.includes("authentication failed") || message.includes("unauthorized") ); } /** * Check if an error represents a database-layer failure. * These errors indicate temporary unavailability — user should retry. */ export function isDatabaseError(error: unknown): boolean { if (!(error instanceof Error)) return false; const msg = error.message.toLowerCase(); return ( msg.includes("pool") || msg.includes("postgres") || msg.includes("database") || msg.includes("sql") || // drizzle-orm wraps all failed queries as: "Failed query: \nparams: " msg.includes("failed query") ); }