Error Handling
All operations return a Result type with either data or error. The library provides rich error types that help you handle different error scenarios appropriately.
Basic Error Checking
const result = await db.from(users).list().execute();
if (result.error) {
console.error("Query failed:", result.error.message);
return;
}
if (result.data) {
console.log("Query succeeded:", result.data);
}HTTP Errors
Handle HTTP status codes (4xx, 5xx) with the HTTPError class:
import { HTTPError, isHTTPError } from "@proofkit/fmodata";
const result = await db.from(users).list().execute();
if (result.error) {
if (isHTTPError(result.error)) {
// TypeScript knows this is HTTPError
console.log("HTTP Status:", result.error.status);
if (result.error.isNotFound()) {
console.log("Resource not found");
} else if (result.error.isUnauthorized()) {
console.log("Authentication required");
} else if (result.error.is5xx()) {
console.log("Server error - try again later");
} else if (result.error.is4xx()) {
console.log("Client error:", result.error.statusText);
}
// Access the response body if available
if (result.error.response) {
console.log("Error details:", result.error.response);
}
}
}Network Errors
Handle network-level errors (timeouts, connection issues, etc.):
import {
TimeoutError,
NetworkError,
RetryLimitError,
CircuitOpenError,
} from "@proofkit/fmodata";
const result = await db.from(users).list().execute();
if (result.error) {
if (result.error instanceof TimeoutError) {
console.log("Request timed out");
// Show user-friendly timeout message
} else if (result.error instanceof NetworkError) {
console.log("Network connectivity issue");
// Show offline message
} else if (result.error instanceof RetryLimitError) {
console.log("Request failed after retries");
// Log the underlying error: result.error.cause
} else if (result.error instanceof CircuitOpenError) {
console.log("Service is currently unavailable");
// Show maintenance message
}
}Validation Errors
When schema validation fails, you get a ValidationError with rich context:
import { ValidationError, isValidationError } from "@proofkit/fmodata";
const result = await db.from(users).list().execute();
if (result.error) {
if (isValidationError(result.error)) {
// Access validation issues (Standard Schema format)
console.log("Validation failed for field:", result.error.field);
console.log("Issues:", result.error.issues);
console.log("Failed value:", result.error.value);
}
}Validator-Agnostic Error Handling
The library uses Standard Schema to support any validation library (Zod, Valibot, ArkType, etc.). The ValidationError.cause property contains the normalized Standard Schema issues array:
import { ValidationError } from "@proofkit/fmodata";
const result = await db.from(users).list().execute();
if (result.error instanceof ValidationError) {
// The cause property (ES2022 Error.cause) contains the Standard Schema issues array
// This is validator-agnostic and works with Zod, Valibot, ArkType, etc.
console.log("Validation issues:", result.error.cause);
console.log("Issues are also available directly:", result.error.issues);
// Both point to the same array
console.log(result.error.cause === result.error.issues); // true
// Access additional context
console.log("Failed field:", result.error.field);
console.log("Failed value:", result.error.value);
// Standard Schema issues have a normalized format
result.error.issues.forEach((issue) => {
console.log("Path:", issue.path);
console.log("Message:", issue.message);
});
}OData Errors
Handle OData-specific protocol errors:
import { ODataError, isODataError } from "@proofkit/fmodata";
const result = await db.from(users).list().execute();
if (result.error) {
if (isODataError(result.error)) {
console.log("OData Error Code:", result.error.code);
console.log("OData Error Message:", result.error.message);
console.log("OData Error Details:", result.error.details);
}
}Error Handling Patterns
Pattern 1: Using instanceof
import {
HTTPError,
ValidationError,
TimeoutError,
NetworkError,
} from "@proofkit/fmodata";
const result = await db.from(users).list().execute();
if (result.error) {
if (result.error instanceof TimeoutError) {
showTimeoutMessage();
} else if (result.error instanceof HTTPError) {
if (result.error.isNotFound()) {
showNotFoundMessage();
} else if (result.error.is5xx()) {
showServerErrorMessage();
}
} else if (result.error instanceof ValidationError) {
showValidationError(result.error.field, result.error.issues);
} else if (result.error instanceof NetworkError) {
showOfflineMessage();
}
}Pattern 2: Using kind property (for exhaustive matching)
const result = await db.from(users).list().execute();
if (result.error) {
switch (result.error.kind) {
case "TimeoutError":
showTimeoutMessage();
break;
case "HTTPError":
handleHTTPError(result.error.status);
break;
case "ValidationError":
showValidationError(result.error.field, result.error.issues);
break;
case "NetworkError":
showOfflineMessage();
break;
case "ODataError":
handleODataError(result.error.code);
break;
// TypeScript ensures exhaustive matching!
}
}Pattern 3: Using type guards
import {
isHTTPError,
isValidationError,
isODataError,
isNetworkError,
} from "@proofkit/fmodata";
const result = await db.from("users").list().execute();
if (result.error) {
if (isHTTPError(result.error)) {
// TypeScript knows this is HTTPError
console.log("Status:", result.error.status);
} else if (isValidationError(result.error)) {
// TypeScript knows this is ValidationError
console.log("Field:", result.error.field);
console.log("Issues:", result.error.issues);
} else if (isODataError(result.error)) {
// TypeScript knows this is ODataError
console.log("Code:", result.error.code);
} else if (isNetworkError(result.error)) {
// TypeScript knows this is NetworkError
console.log("Network issue:", result.error.cause);
}
}Error Properties
All errors include helpful metadata:
if (result.error) {
// All errors have a timestamp
console.log("Error occurred at:", result.error.timestamp);
// All errors have a kind property for discriminated unions
console.log("Error kind:", result.error.kind);
// All errors have a message
console.log("Error message:", result.error.message);
}Available Error Types
HTTPError- HTTP status errors (4xx, 5xx) with helper methods (is4xx(),is5xx(),isNotFound(), etc.)ODataError- OData protocol errors with code and detailsValidationError- Schema validation failures with issues, schema reference, and failed valueResponseStructureError- Malformed API responsesRecordCountMismatchError- Whensingle()ormaybeSingle()expectations aren't metTimeoutError- Request timeout (from ffetch)NetworkError- Network connectivity issues (from ffetch)RetryLimitError- Request failed after retries (from ffetch)CircuitOpenError- Circuit breaker is open (from ffetch)AbortError- Request was aborted (from ffetch)BatchTruncatedError- Batch operation was truncated due to an earlier error
