Skip to content
BunBase BunBase BunBase Docs Alpha v0.1.0

Error Handling

All SDK methods throw BunBaseError on non-2xx responses.

import { BunBaseError } from "@bunbase/js";
try {
await client.auth.login({ email, password });
} catch (err) {
if (err instanceof BunBaseError) {
console.log(err.message); // "Invalid email or password."
console.log(err.status); // 401
console.log(err.code); // machine-readable code, e.g. "invalid_credentials"
console.log(err.field); // field name for validation errors, e.g. "email"
console.log(err.body); // raw server response body
}
}

When the server returns a validation error tied to a specific field, err.field is set. Use this to display inline form errors:

} catch (err) {
if (err instanceof BunBaseError && err.field) {
setFieldErrors({ [err.field]: err.message });
} else {
setError(err instanceof Error ? err.message : "Something went wrong.");
}
}
StatusCause
400Validation error
401Not authenticated or session expired
403Forbidden — insufficient permissions
404Record or resource not found
409Conflict — e.g. email already registered
413File too large for bucket
415MIME type not allowed by bucket
429Rate limit exceeded

System fields on every record:

interface BunBaseRecord {
_id: string; // ULID — unique, time-ordered
_created_at: number; // Unix ms
_updated_at: number; // Unix ms
_owner_id: string | null;
_deleted_at?: number | null;
}
interface ListResult<T> {
items: T[];
total: number;
page: number;
limit: number;
next_cursor: string | null;
}
interface AuthResult {
access_token: string;
refresh_token: string;
expires_in: number;
user: AuthUser;
}
interface AuthUser {
id: string;
email: string;
created_at: number;
updated_at: number;
is_verified: boolean;
}
interface FileRecord {
id: string;
key: string;
bucket: string;
filename: string | null; // original filename, e.g. "photo.jpg"
collection: string | null;
record_id: string | null;
owner_id: string | null;
size: number;
mime_type: string;
is_public: boolean;
created_at: number;
}

Pass filename to client.storage.downloadUrl(id, filename) to produce an extension-aware URL (e.g. /api/v1/storage/01JKX.../photo.jpg). This helps browsers and CDNs identify the file type from the URL path.

login() returns LoginResult, which is either AuthResult or a TotpChallenge:

type LoginResult = AuthResult | TotpChallenge;
interface TotpChallenge {
totp_required: true;
totp_token: string; // short-lived — pass to verifyTotp()
}

Check which branch you received:

const result = await client.auth.login({ email, password });
if ("totp_required" in result) {
// 2FA step required
} else {
// result is AuthResult — user is signed in
}
interface ApiKey {
id: string;
name: string;
created_at: number; // Unix ms
}

createApiKey() returns ApiKey & { key: string } — the key field (bb_...) is only present on creation. Store it securely; it cannot be retrieved again.

type RealtimeEventType = "create" | "update" | "delete";
interface RealtimeEvent<T = BunBaseRecord> {
event: RealtimeEventType;
collection: string;
record: T & BunBaseRecord;
}
interface ListQuery<T> {
filter?: Filter<T>;
sort?: string; // prefix "-" for descending
page?: number;
limit?: number;
fields?: string[];
expand?: string[];
after?: string; // cursor — replaces page when set
include_deleted?: boolean;
}