All typed failures thrown by @fairmint/canton-node-sdk derive from CantonError, which itself subclasses @hardlydifficult/rest-client’s RestClientError. That lets shared HTTP tooling pattern-match either hierarchy.
Use instanceof checks in handlers and inspect .context (serializable Record<string, unknown>) or ApiError’s HTTP fields where applicable.
import {
CantonError,
ConfigurationError,
AuthenticationError,
ApiError,
ValidationError,
NetworkError,
OperationError,
ErrorCode,
OperationErrorCode,
} from '@fairmint/canton-node-sdk';
Hierarchy overview
| Class | Code (ErrorCode or custom) | Typical causes |
|---|---|---|
CantonError | CANTON_ERROR | Base class; rarely thrown directly. |
ConfigurationError | CONFIGURATION_ERROR | Missing CANTON_* vars, invalid NODE_ENV, unresolved API config in EnvLoader / BaseClient, missing party id when required. |
AuthenticationError | AUTHENTICATION_ERROR | OAuth failures surfaced by rest-client stack during token exchange (exact mapping depends on caller). |
ApiError | API_ERROR | Participant returned non-2xx; carries optional status, statusText, and context payload from the HTTP layer. |
ValidationError | VALIDATION_ERROR | Parameter validation before network I/O (for example numeric parsing in helpers such as createParty). |
NetworkError | NETWORK_ERROR | Transport-level failures (DNS, socket) classified by HTTP client. |
OperationError | operation-specific (OperationErrorCode.*) | Higher-level orchestration failures (waitForCondition timeout uses TRANSACTION_FAILED). |
OperationErrorCode includes values such as MISSING_CONTRACT, MISSING_DOMAIN_ID, INSUFFICIENT_FUNDS, INVALID_AMOUNT, INVALID_PARAMETER, MINING_ROUND_NOT_FOUND, PARTY_CREATION_FAILED, TRANSACTION_FAILED.
Example — narrow errors from a ledger call
import {
ApiError,
Canton,
ConfigurationError,
ValidationError,
} from '@fairmint/canton-node-sdk';
const canton = new Canton({
network: 'devnet',
provider: '5n',
partyId: 'OWN_PARTY_ID',
});
try {
await canton.ledger.getActiveContracts({});
} catch (err) {
if (err instanceof ConfigurationError) {
console.error('Fix env', err.message);
} else if (err instanceof ApiError) {
console.error('HTTP', err.status, err.message);
} else if (err instanceof ValidationError) {
console.error('Bad params', err.message);
}
throw err;
}
When each error appears
ConfigurationError:EnvLoader.getCurrentNetwork()/getCurrentProvider()validation; missing auth URL; missing API URI/client id triplet ingetConfig; missing party id when loading env-backedApiConfig;BaseClient.getPartyId()when no party configured;getNodeEnv()invalid value.AuthenticationError: Propagated when token acquisition fails (credentials wrong, IdP unreachable within auth layer classification).ApiError: Ledger / validator / scan HTTP responses with error status after rest-client handling.ValidationError: Input validation in SDK helpers before submitting requests.NetworkError: Low-level request failures without HTTP semantics.OperationError: Business-operation wrappers;waitForConditionthrowsOperationErrorwith codeTRANSACTION_FAILEDon timeout.
Pitfalls
ApiError.contextvs.response:ApiErrorexposes deprecated getterresponseas alias forcontext; prefercontextfor new code.- String-only catches: Downstream libraries may throw plain
Error; keep a generic fallback branch.
See also
- BaseClient —
ConfigurationErrorwhen party/API missing. - EnvLoader — configuration errors during env merge.
waitForCondition—OperationErroron timeout.
Source
src/core/errors.ts on GitHub.