Reference for Canton error codes, categories, gRPC status mappings, and retry strategies
Canton returns structured error information through gRPC responses. Every error carries a machine-readable code, a category that determines the gRPC status code, and a human-readable description. You can use these components to build automated error handling in your application.
Each gRPC error response includes structured details following the rich gRPC error model:
ErrorInfo (mandatory) — contains the error code ID in reason and the category ID in metadata["category"]
RequestInfo (mandatory) — contains the full correlation ID (not truncated) in requestId
RetryInfo (optional) — contains the recommended retry interval when the error is retryable
ResourceInfo (optional) — identifies the resource involved in the failure (contract, contract key, package, party, synchronizer, etc.)
Some errors are redacted for security. The API response omits sensitive details, but the full error message appears in server-side logs. Work with your operator if you need the complete error context.
Categories 1, 2, and 3 represent transient conditions. Your application should retry these automatically. For category 1 (UNAVAILABLE), retry quickly — a load balancer can handle this. For category 2 (ABORTED), use exponential backoff since the issue is resource contention. For category 3 (DEADLINE_EXCEEDED), retry a limited number of times and use command deduplication to avoid duplicate submissions.
These errors indicate a problem with the request itself. Category 6 (UNAUTHENTICATED) means your JWT token is missing or invalid. Category 7 (PERMISSION_DENIED) means the token lacks the required rights. Category 8 (INVALID_ARGUMENT) means the request is malformed regardless of system state. Fix the issue in your application or configuration before retrying.
These errors depend on the current state of the ledger. A CONTRACT_NOT_FOUND (category 11) might be expected in a multi-party workflow where another party archived the contract, or it might indicate an application bug. Your handling strategy depends on your application’s logic.
The following Scala example shows how to extract error components from a StatusRuntimeException:The following Java example shows the equivalent extraction. Java has first-class codegen support in Canton, so this is the most common non-Scala pattern:
import com.google.rpc.ErrorInfo;import com.google.rpc.RequestInfo;import com.google.rpc.RetryInfo;import io.grpc.StatusRuntimeException;import io.grpc.protobuf.StatusProto;try { // your gRPC call here} catch (StatusRuntimeException e) { com.google.rpc.Status status = StatusProto.fromThrowable(e); // gRPC status code int code = status.getCode(); // Full error description String message = status.getMessage(); // Extract structured details for (com.google.protobuf.Any detail : status.getDetailsList()) { if (detail.is(ErrorInfo.class)) { ErrorInfo info = detail.unpack(ErrorInfo.class); String errorId = info.getReason(); String category = info.getMetadataMap().get("category"); } if (detail.is(RequestInfo.class)) { String requestId = detail.unpack(RequestInfo.class).getRequestId(); } if (detail.is(RetryInfo.class)) { RetryInfo retry = detail.unpack(RetryInfo.class); long retryMs = retry.getRetryDelay().getSeconds() * 1000 + retry.getRetryDelay().getNanos() / 1_000_000; } }}
These error codes are also surfaced through the JSON API (HTTP Ledger API) with equivalent error detail structures. For other languages, use the equivalent gRPC status and protobuf utilities to unpack com.google.rpc.Status details from the trailing metadata.
Note that all error codes emitted by Canton are documented in the Error Inventory.Whenever you observe an error, search for the corresponding error code in the inventory to find the explanation and
the recommended resolution.The error code reference documentation is maintained directly in the Canton source code.