Find the next step.
Diagnose asset loading, wallet setup, protocol errors, and delayed settlement.
On this page
Asset loading
If the worker fails to initialize, inspect the browser’s Network panel before changing wallet code.
- Open
/zkapi/browser-config.jsonand confirm that it returns JSON. - Check
/zkapi/assets/zkapiWasmWorker.jsand the referenced WASM and proof files. - Ensure the asset paths return their actual files, not your router’s HTML fallback.
- Regenerate the assets for the selected deployment.
init() can resolve after a readiness failure. For diagnostics in browser code, call client.ensureReady() and inspect the thrown error.
Wallet and network
Register the provider with purseClient().setWalletProvider(provider) before requesting a wallet operation. Confirm that the connected account and chain match your deployment.
For wallet_rejected, let the person initiate another attempt. For Sepolia access failures, obtain the operator’s testnet access credentials through its normal process.
Error catalog
Map protocol codes to readable messages using the exported catalog. Display the message next to the action that failed.
import { getErrorCatalogEntry } from "@openzk.app/purse";
const entry = getErrorCatalogEntry(errorCode);
// entry.code, entry.userMessage, entry.action, entry.severity| Code | Recovery action | Message |
|---|---|---|
stale_root | resync_retry | Your balance check is out of date. Refreshing now. |
replay | fresh_retry | That request was already counted. Sending a new one. |
native_quote_expired | fresh_retry | The price changed. Getting a fresh one. |
native_quote_superseded | fresh_retry | The price changed. Getting a fresh one. |
nullifier_used | halt | This balance was already spent somewhere else. |
lease_pending | backoff | Finishing up the last request. One moment. |
note_expired | route_exit | This balance expired. Withdraw any remaining funds. |
invalid_proof | halt | Something went wrong verifying your balance. Nothing was charged. |
protocol_mismatch | halt | This app needs a refresh. Reload the page. |
invalid_request | halt | That request could not be sent. Try again. |
oa_minute_request_limit | backoff | The service is busy. Trying again in a moment. |
oa_hourly_issuance_budget | backoff | The service is busy right now. Please try again later. |
oa_rate_limited | backoff | The service is busy. Trying again in a moment. |
capacity_exhausted | backoff | Temporarily unavailable. Please try again shortly. |
network_error | halt | Connection lost. Check your internet and try again. |
upstream_error | halt | The model service reported a problem. You only pay for what was used. |
insufficient_chat_balance | halt | This purchase costs more than your private balance. Fund a larger balance, then try again. |
wallet_rejected | halt | The wallet request was declined. Nothing was sent. |
Unknown codes use the catalog’s fallback message and halt action.
Retry policy
The exported executeWithSingleRetry helper retries once for catalog actions resync_retry and fresh_retry. Supply a recovery callback to refresh whatever state the operation requires.
backoff, halt, and route_exit return a failure result from this helper. They are not automatically retried, delayed, or redirected. The payment hooks do not wrap every action in this retry helper.
Settlement
Inference streaming and note settlement are separate phases. The burn hook releases the lease, asks for settlement, and briefly waits for the refreshed balance to decrease before recording the cost.
If that balance update has not arrived, the receipt can show settled onchain without a resolved local cost. Treat that display as pending cost information, not proof of a free request.
Read the lease lifecycle and state-subscription APIs.
Documentation for the OpenZK browser toolkit. Report a documentation issue ↗