Skip to main content

Error Handling

The driver throws strongly-typed exceptions inheriting from the base BastionError class.


1. Catching Errors​

import {
BastionClient,
BastionError,
NotFoundError,
QuotaExceededError,
PasswordChangeRequiredError,
BastionAuthError,
} from "@liorans3/driver";

const client = new BastionClient("bastion://admin:YOUR_PASSWORD@127.0.0.1:27118");
const bucket = client.bucket("documents");

try {
const obj = await bucket.get("missing-report.pdf");
await obj.writeToFile("./report.pdf");
} catch (error: unknown) {
if (error instanceof NotFoundError) {
console.error("The requested object or bucket does not exist.");
} else if (error instanceof QuotaExceededError) {
console.error("Bucket storage quota has been reached.");
} else if (error instanceof PasswordChangeRequiredError) {
console.error("Bootstrap admin password must be changed before proceeding.");
} else if (error instanceof BastionAuthError) {
console.error("Invalid username, password, or access key secret.");
} else if (error instanceof BastionError) {
console.error(`API Error [${error.code}] (HTTP ${error.status}): ${error.message}`);
} else {
console.error("Unexpected failure:", error);
}
}

2. Error Class Hierarchy​

All errors extend BastionError, which provides:

  • error.code: Server error code string (e.g. "object_not_found").
  • error.status: HTTP status code integer (e.g. 404).
  • error.message: Human-readable error description.
  • error.isRetryable: Boolean indicating if the operation can be retried safely.
BastionError (Base)
├── BastionAuthError (HTTP 401)
├── PasswordChangeRequiredError (HTTP 403)
├── BastionForbiddenError (HTTP 403)
├── NotFoundError (HTTP 404)
├── AlreadyExistsError (HTTP 409)
├── InvalidInputError (HTTP 400)
├── ConnectionError (Network / DNS / Socket Failure)
├── RangeNotSatisfiableError (HTTP 416)
├── QuotaExceededError (HTTP 507)
└── StorageCapacityExhaustedError (HTTP 507)

3. Server Error Code Mapping​

Error ClassHTTP StatusServer Error Code (code)Meaning
BastionAuthError401 Unauthorizedinvalid_credentials, unauthorizedMissing, incorrect, or expired credentials.
PasswordChangeRequiredError403 Forbiddenpassword_change_requiredBootstrap admin account must rotate initial password.
BastionForbiddenError403 ForbiddenforbiddenAuthenticated role lacks required permission.
NotFoundError404 Not Foundbucket_not_found, object_not_found, user_not_found, upload_not_found, access_key_not_foundTarget resource does not exist.
AlreadyExistsError409 Conflictbucket_already_exists, user_already_existsEntity with this name already exists.
InvalidInputError400 Bad Requestinvalid_input, invalid_uriMalformed parameters, invalid key format, or bad range.
QuotaExceededError507 Insufficient Storagequota_exceededBucket byte quota limit exceeded.
StorageCapacityExhaustedError507 Insufficient Storagestorage_capacity_exhaustedHost storage disk below minimum safety watermark.
RangeNotSatisfiableError416 Range Not Satisfiablerange_not_satisfiableRequested byte offset exceeds total object size.
ConnectionError0 (Client-side)connection_errorConnection refused, timeout, or network disconnect.

4. Retry Guidelines​

The driver flags transient network failures and 5xx server errors with isRetryable = true.

async function fetchWithRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
let attempt = 0;
while (true) {
try {
return await fn();
} catch (err) {
attempt++;
if (err instanceof BastionError && err.isRetryable && attempt < maxRetries) {
const backoffMs = Math.pow(2, attempt) * 200;
await new Promise((res) => setTimeout(res, backoffMs));
continue;
}
throw err;
}
}
}