Errors and retries
API and SDK failures derive from FlashdriveError. Catch a more specific exception when your application can take a useful action. Local validation mistakes can raise ValueError; local file operations can raise standard Python errors such as FileNotFoundError.
Report a failed request
The error’s code and request_id help you diagnose a failed operation without logging the API key or document content:
import os
from flashdrive import Flashdrive, FlashdriveError
with Flashdrive(drive_id=os.environ["FLASHDRIVE_DRIVE_ID"]) as client:
try:
page = client.files.full_text_search("onboarding checklist")
print("Results:", len(page.results))
except FlashdriveError as error:
print("Code:", error.code)
print("HTTP status:", error.status)
print("Request ID:", error.request_id)
raise| Exception | What to do |
|---|---|
AuthenticationError | Check that the key is current and belongs to the intended workspace. |
PermissionDeniedError | Use a key with the required permission or ask a workspace administrator for access. |
NotFoundError | Check the drive or document ID and the key’s workspace. |
PreconditionFailedError | Read the latest file and reconcile changes before a new write. |
ConflictError | Inspect the error code and resolve the conflicting state. |
RateLimitError | Respect retry_after and reduce request concurrency. |
QuotaExceededError | Check the applicable drive or account limit before retrying. |
PaymentRequiredError | Review the account’s billing status in the Console. |
ServiceUnavailableError | Retry only when the error permits it, with a bounded delay. |
UploadBatchError | Preserve completed receipts and inspect each failed file. |
UploadTimeoutError | Resume a queued receipt if present; do not assume the upload was rejected. |
Decide whether to retry
An error includes advice for the particular failure:
retry_unchangedsays whether the same request can succeed after waiting.retry_aftergives a delay in seconds when the service supplies one.retry_with_same_keysays whether a retry must retain the operation’s idempotency key.is_retryablealso includes failures that need a change first. It is not a safe condition for an unchanged retry loop.
The SDK already retries some transient requests within the call’s deadline. If your application retries after a call fails, bound the attempt count and overall elapsed time. Never repeatedly submit an unchanged revision conflict.
Keep a write’s identity across retries
An idempotency key identifies one intended operation. Persist it before the first request, then reuse it with the same body and observed revision if the error permits that retry. Changing the content or accepting a newly read revision creates a new operation and needs a new key.
For uploads, also keep the upload ID, drive ID, and any receipt returned with an error. uploads.resume() continues polling a transferred upload. A partial batch’s batch.files contains completed receipts; retrying everything under new keys can duplicate work. See upload recovery.
Review a processing failure
A write can be accepted before indexing completes. Use its operation ID to read the outcome:
import os
from flashdrive import Flashdrive
operation_id = input("Operation ID: ").strip()
with Flashdrive(drive_id=os.environ["FLASHDRIVE_DRIVE_ID"]) as client:
operation = client.operations.get(operation_id)
print(operation.status)
if operation.status == "failed":
print(operation.error_code, operation.error_message)queued or running means processing is still in progress. Use a bounded polling interval appropriate to your job rather than a tight loop. A timeout means the client stopped waiting; it does not prove that the server cancelled the work.