Error Handling

This page collects every sentinel error exposed by the Go SDK, the REST error envelope, and the transient-vs-permanent error classification used by the SDK's polling loops.

REST error envelope

Every non-2xx HTTP response uses the same shape:

{
  "type": "NOT_FOUND",
  "code": "WALLET_NOT_FOUND",
  "message": "The requested resource was not found."
}

typeNOT_FOUND | VALIDATION_ERROR | CONFLICT | INTERNAL_ERROR | ORGANIZATION_NOT_FOUND. The code field provides a machine-readable error code for NOT_FOUND and CONFLICT responses (e.g. CHANNEL_NOT_FOUND, OPERATION_NOT_FINALIZABLE, IDEMPOTENCY_KEY_MISMATCH). See the REST API Reference for the full table.

Transient vs permanent errors

The SDK does not layer automatic HTTP-level retries on top of API calls. Each method on wallets.Client, channels.Client, events.Client, and transact.Client issues its request once and surfaces any error to the caller.

The exception is the watchers.Client polling helpers, WaitForActive and WaitForArchived. These methods poll Get on a time.Ticker (default 2 * time.Second, configurable via crec.WithWatcherPolling). When Get returns a transient error, the loop logs it and continues to the next tick instead of aborting; permanent errors abort the wait immediately.

The transient/permanent classification is implemented in watchers.go (isTransientError / isTransientStatusCode):

Status codeClassificationBehaviour inside WaitForActive / WaitForArchived
429 Too Many RequestsTransientLoop continues to the next poll tick
500599TransientLoop continues to the next poll tick
Network errors (connection refused/reset, timeout, EOF, no such host, network unreachable, broken pipe, temporary failure)TransientLoop continues to the next poll tick
400499 (excluding 429)PermanentWait aborts; error returned to caller
Any other error not matched aboveTreated as permanentWait aborts

For all other sub-clients, retry behaviour is your responsibility. If you wrap calls in your own retry loop, base the transient check on errors.Is(err, …) against the sentinel errors documented below, or on the HTTP status code returned in the REST error envelope.

Common symptoms: what to do

If you're hitting a specific error and just want to know what to fix, find the symptom below first. The full sentinel-error catalog (organised per SDK package) is in the next section.

Symptom (what you see)Likely causeFix
crec.ErrBaseURLRequired / ErrAPIKeyRequired on NewClientCREC_BASE_URL / CREC_API_KEY env var unset or passed as "".Set both before constructing the client; see Authentication.
401 Unauthorized from any endpointAPI key not sent, sent in the wrong header, or for the wrong environment.The header is Authorization: Apikey <key>. The Go SDK sets it for you; for raw curl see REST API Reference.
wallets.ErrStatusChannelIDZero on Wallets.CreateStatusChannelId was supplied as the zero UUID.Pass a real channel ID, or omit the field entirely; see Create and Manage Wallets.
transact.ErrInvalidDeadline or types.ErrOperationDeadlineRequired on ExecuteOperationOperation.Deadline is now mandatory.Set Deadline: big.NewInt(0) for "no expiration" or a Unix-seconds value; see Build and Sign Operations.
eip712.ErrUnsupportedChainFamily on signingThe chain selector resolves to a non-EVM chain.EVM is the only supported family today; pick a different chain selector via Supported Networks.
events.ErrVerificationNotConfigured on Events.VerifyClient built without crec.WithEventVerification(...).Configure verification at construction time; see Verify Event Signatures.
events.ErrNoOCRProofs on Events.Verify / VerifyOperationStatusThe event record returned by the API has no Off-Chain Reporting (OCR) proof attached.Skip the event with errors.Is(err, events.ErrNoOCRProofs) and re-poll on the next cycle.
events.ErrInvalidEventHash / ErrMultipleOCRProofsThe event payload is malformed, tampered, or wasn't produced by your tenant's watcher.Re-fetch the event with Events.SearchEvents (filtered by EventId) or GET /channels/{channel_id}/events/search/{event_id}; if it persists, the watcher source is the problem. See Event Verification.
events.ErrOrgIDOrWorkflowOwnerReq / ErrWorkflowOwnerRequiredVerification needs an org context the SDK couldn't resolve.Pass crec.WithOrgID(os.Getenv("CREC_ORG_ID")) or WithWorkflowOwner(...) at client construction time. There is no default.
watchers.ErrWaitForActiveTimeout / ErrWatcherDeploymentFailedWaitForActive exceeded its deadline, or the watcher transitioned to failed.Inspect the latest watcher.status event for status_reason. Most failures are bad ABI / address / chain selector; see Manage Watcher Lifecycle.
watchers.ErrWatcherIsArchiving / ErrWatcherAlreadyArchivedYou called WaitForActive on a watcher that's already being torn down.Recreate the watcher; archived watchers cannot be reactivated.
wallets.ErrDuplicateEcdsaSigner / ErrDuplicateRsaSignerTwo identical entries in the signer list.Deduplicate before calling Create.
transact.ErrChannelNotFound on ExecuteOperationWrong channelID, or the channel was archived.Confirm with Channels.Get; recreate or pick a different channel.
fireblocks.ErrEnvFireblocksAPIKey (etc.)FIREBLOCKS_* env var missing when calling FromEnv.Set every FIREBLOCKS_API_KEY / _API_SECRET / _VAULT_ACCOUNT_ID / _ASSET_ID; see Fireblocks Signer.
privy.ErrEnvPrivyAppIDNotSet (etc.)PRIVY_* env var missing when calling FromEnv.Set PRIVY_APP_ID / _APP_SECRET / _WALLET_ID; see Privy Signer.
429 Too Many Requests on watcher endpointsRate-limited. Inside WaitForActive / WaitForArchived the polling loop classifies this as transient and continues to the next tick.Increase the poll interval with crec.WithWatcherPolling(...). For all other client methods, the SDK does not retry: wrap the call in your own retry logic.
404 Not Found on a wallet_id / watcher_id / operation_idThe resource was archived, never existed, or belongs to a different channel.Re-list within the right channel; check archive status.

If the symptom isn't here, look up the exact Err… value in the per-package catalog below.

Sentinel errors by package

All sentinel errors are exported var Err… values. Check with errors.Is(err, pkg.ErrSomething).

crec (root)

ErrorReturned by
crec.ErrBaseURLRequiredNewClient / NewAPIClient when baseURL == "".
crec.ErrAPIKeyRequiredNewClient / NewAPIClient when apiKey == "".
crec.ErrInvalidEventVerificationConfigNewClient when validSigners is set but minRequiredSignatures <= 0.
crec.ErrIncompleteDONConfigNewClient when WithDONConfig was used but the DON unit is incomplete.
crec.ErrListNetworksClient.ListNetworks when the underlying API call fails.
crec.ErrNilResponseClient.ListNetworks when the API client returns a nil response.

apierror (conflict sentinels)

HTTP 409 responses are mapped to canonical sentinels based on ApplicationError.code, so errors.Is works across packages:

ErrorTrigger (ApplicationError.code)
apierror.ErrChannelAlreadyExistsCHANNEL_ALREADY_EXISTS
apierror.ErrWalletAlreadyExistsWALLET_ALREADY_EXISTS
apierror.ErrWatcherAlreadyExistsWATCHER_ALREADY_EXISTS
apierror.ErrIdempotencyKeyMismatchIDEMPOTENCY_KEY_MISMATCH
apierror.ErrOperationNotFinalizableOPERATION_NOT_FINALIZABLE
apierror.ErrOperationNotCancellableOPERATION_NOT_CANCELLABLE
apierror.ErrOperationDeadlineElapsedOPERATION_DEADLINE_ELAPSED
apierror.ErrWalletAlreadyArchivedWALLET_ALREADY_ARCHIVED
apierror.ErrChainUnavailableCHAIN_UNAVAILABLE

An unrecognized or missing code returns no sentinel (forward-compatible for codes added after this SDK release).

channels

ErrorNotes
channels.ErrChannelNotFound404 lookup.
channels.ErrOptionsRequired, ErrAPIClientRequiredConstructor validation.
channels.ErrChannelNameRequired, ErrChannelNameTooLongChannel name validation.
channels.ErrCreateChannel, ErrGetChannel, ErrListChannels, ErrUpdateChannel, ErrArchiveChannelAPI call failures (wrap the underlying error).
channels.ErrUnexpectedStatusCode, ErrNilResponse, ErrNilResponseBodyHTTP-layer issues.

events

ErrorNotes
events.ErrChannelIDRequiredMissing channel_id parameter.
events.ErrOptionsRequired, ErrCRECClientRequiredConstructor validation.
events.ErrChannelNotFoundChannel does not exist (404).
events.ErrPollEvents, ErrSearchEvents, ErrGetEventsAPI call failed; wraps the underlying status.
events.ErrVerifyEventVerification failed; check the wrapped cause.
events.ErrWorkflowOwnerMismatchThe workflow owner embedded in the OCR report differs from the expected owner.
events.ErrInsufficientValidSignaturesThe OCR proof does not reach the configured signature threshold.
events.ErrInvalidEventHashThe supplied event hash doesn't match the verifiable payload.
events.ErrNoOCRProofs / ErrMultipleOCRProofsThe verifiable event has zero or more than one OCR proof.
events.ErrParseSignature, ErrRecoverPubKeyFromSignatureSignature mechanics failed (corrupted payload).
events.ErrParseOCRReport, ErrParseOCRContext, ErrOCRReportTooShortMalformed OCR report.
events.ErrParseEventPayload, ErrMarshalEventPayload, ErrMarshalEventToJSONEncoding round-trip failure.
events.ErrDecodeEvent, ErrDecodeVerifiableEventDecoding failed; check ABI / payload.
events.ErrOnlyWatcherEventsSupportedVerify was called on a non-watcher.event event.
events.ErrOnlyOperationStatusSupportedVerifyOperationStatus was called on a non-operation.status event.
events.ErrOnlyQueryStatusSupportedVerifyQueryStatus was called on a non-query.status event.
events.ErrVerificationNotConfiguredEmpty signer set; configure WithEventVerification.
events.ErrOrgIDRequired, ErrWorkflowOwnerRequired, ErrOrgIDOrWorkflowOwnerReqMissing identity context for verification: supply via options or per-call.
events.ErrDeriveWorkflowOwnerWithCRETenantID derivation failed.
events.ErrUnexpectedStatusCode, ErrNilResponse, ErrNilResponseBody, ErrBadRequestHTTP-layer issues.
events.ErrInvalidMinRequiredSignatures, ErrInvalidSignerAddress, ErrDuplicateSigner, ErrMinSignersExceedsUniqueVerification configuration validation (WithEventVerification).
events.ErrNilWatcherEventPayload, ErrVerifiableEventRequired, ErrNilVerifiablePayloadHashing/decoding called with nil or empty payload.
events.ErrDecodeNilEvent, ErrDecodeNilEventID, ErrDecodeNilEventProofsDecode was called with an event missing required fields.
events.ErrDecodeVerifiableEmpty, ErrDecodeVerifiableNilOrEmpty, ErrDecodeVerifiableInvalidBase64, ErrDecodeVerifiableInvalidJSONDecodeVerifiableEvent was called with a malformed verifiable payload.
events.ErrInvalidOCRSignatureLength, ErrInvalidOCRSignatureRecoveryOCR signature is not 65 bytes or has an invalid recovery byte.

watchers

ErrorNotes
watchers.ErrWatcherNotFound404 lookup.
watchers.ErrChannelIDRequired, ErrWatcherIDRequired, ErrNameRequiredArgument validation.
watchers.ErrWatcherNameTooShortName must be ≥4 characters.
watchers.ErrServiceRequired, ErrAddressRequired, ErrEventsRequiredMissing required fields on CreateWithService.
watchers.ErrABIRequired, ErrInvalidABIType, ErrEventNotInABICreateWithABI validation.
watchers.ErrChainSelectorRequiredMissing chain_selector.
watchers.ErrWaitForActiveTimeoutWaitForActive exceeded its deadline.
watchers.ErrWaitForArchivedTimeoutWaitForArchived exceeded its deadline.
watchers.ErrWatcherDeploymentFailedWatcher transitioned to failed.
watchers.ErrWatcherIsArchiving, ErrWatcherAlreadyArchived, ErrWatcherArchiveFailedTerminal-state errors during waits.
watchers.ErrUnexpectedStatus, ErrEmptyResponse, ErrNilResponseHTTP-layer issues.
watchers.ErrCreateWatcherRequest, ErrCreateWatcherService, ErrCreateWatcherABI, ErrListWatchers, ErrGetWatcher, ErrUpdateWatcher, ErrArchiveWatcher, ErrCheckWatcherStatus, ErrUnexpectedStatusCodeAPI-call failures (wrap the underlying error).

wallets

ErrorNotes
wallets.ErrWalletNotFound404 lookup.
wallets.ErrNameRequired, ErrNameTooLongName validation.
wallets.ErrChainSelectorRequired, ErrWalletOwnerAddressRequired, ErrInvalidWalletOwnerAddressRequired fields.
wallets.ErrWalletTypeRequired, ErrUnsupportedWalletTypeWallet type validation.
wallets.ErrWalletIDRequiredMissing wallet_id.
wallets.ErrStatusChannelIDZeroStatusChannelId was supplied as the zero UUID on Create. Omit the field or pass a real channel ID.
wallets.ErrEcdsaSignersRequired, ErrRsaSignersRequiredThe matching signer list is required for the chosen wallet type.
wallets.ErrInvalidSignersForEcdsa, ErrInvalidSignersForRsaWrong signer-list field for the wallet type.
wallets.ErrDuplicateEcdsaSigner, ErrDuplicateRsaSignerThe signer list contains duplicate entries.
wallets.ErrInvalidEcdsaSigner, ErrInvalidRsaSignerMalformed signer entries.
wallets.ErrInvalidLimit, ErrInvalidOffset, ErrInvalidOwnerAddressList-filter validation.
wallets.ErrCreateWallet, ErrGetWallet, ErrListWallets, ErrUpdateWallet, ErrArchiveWallet, ErrUnexpectedStatusCode, ErrNilResponse, ErrNilResponseBodyAPI-call failures.

transact

ErrorNotes
transact.ErrChannelIDRequired, ErrChainSelectorRequired, ErrAddressRequired, ErrWalletOperationIDRequired, ErrAtLeastOneTransactionRequired, ErrSignatureRequiredArgument validation. The SDK also validates Operation.Deadline/ID/Transactions upstream; see transact/types.
transact.ErrInvalidDeadlineDeadline must fit int64 and be ≥0.
transact.ErrChannelNotFound, ErrOperationNotFound404 lookup.
transact.ErrDraftNotFoundDraft operation not found (404).
transact.ErrDraftNotFinalizableOperation is not in pending_signature state (409 OPERATION_NOT_FINALIZABLE).
transact.ErrDraftNotCancellableOperation is not in pending_signature state (409 OPERATION_NOT_CANCELLABLE).
transact.ErrDigestRequired, ErrSignatureRequiredMissing digest or signature on finalize.
transact.ErrCreateOperation, ErrGetOperation, ErrListOperations, ErrSendOperation, ErrUnexpectedStatusCode, ErrNilResponse, ErrNilResponseBodyAPI-call failures.

transact/types

ErrorNotes
types.ErrOperationIDRequired, ErrOperationIDNonNegativeOperation ID is missing or negative.
types.ErrOperationDeadlineRequired, ErrOperationDeadlineNonNegativeOperation Deadline is missing or negative (big.NewInt(0) means no expiration).
types.ErrNoTransactionsOperation must contain at least one transaction.
types.ErrTransactionValueRequired, ErrTransactionValueNonNegativeEach transaction must set a non-negative Value.
types.ErrChainIDNonNegative, ErrFailedParseChainIDEIP-712 domain chain ID validation.

transact/eip712

ErrorNotes
eip712.ErrOperationRequired, ErrSignerRequiredConstructor validation.
eip712.ErrParseChainSelector, ErrGetChainFamily, ErrUnsupportedChainFamily, ErrGetChainID, ErrInvalidChainIDStringChain selector lookup failed.
eip712.ErrCreateTypedData, ErrComputeOperationHash, ErrHashOperation, ErrSignOperationTyped-data assembly, hashing, or signing failed.

transact/signer/fireblocks

ErrorNotes
fireblocks.ErrAPIKeyRequired, ErrPrivateKeyPEMRequired, ErrVaultAccountIDRequired, ErrAssetIDRequiredConstructor validation when configuring the signer programmatically.
fireblocks.ErrEnvFireblocksAPIKey, ErrEnvFireblocksAPISecret, ErrEnvFireblocksVaultAcct, ErrEnvFireblocksAssetIDRequired FIREBLOCKS_* environment variable was not set when using FromEnv.
fireblocks.ErrFailedParsePEMBlock, ErrTrailingGarbageAfterPEM, ErrPrivateKeyNotRSA, ErrFailedParsePrivateKeyProvided API secret is not a valid RSA PEM.
fireblocks.ErrTypedDataNil, ErrNegativeUnsignedTypedValue, ErrFloat64PrecisionLoss, ErrParseTypedDataIntegerStringTyped-data encoding / numeric conversion error.
fireblocks.ErrCreateSigningOperationFailed, ErrCreateTypedMessageOperationFailed, ErrFireblocksOperationTerminal, ErrGetVaultAccountNonOKFireblocks API call failed or operation ended in a terminal non-success state.

transact/signer/privy

ErrorNotes
privy.ErrAppIDRequired, ErrAppSecretRequired, ErrWalletIDRequiredConstructor validation.
privy.ErrEnvPrivyAppIDNotSet, ErrEnvPrivyAppSecretNotSet, ErrEnvPrivyWalletIDNotSetRequired PRIVY_* environment variable was not set when using FromEnv.
privy.ErrPrivyUnauthorized, ErrPrivyRPCUnexpectedStatus, ErrPrivyGetWalletUnexpectedStatusPrivy API call failed (auth or non-2xx response).

Async error states

Some failures don't surface synchronously: they appear as a state transition on a *.status event:

StateMeaningRecovery
WatcherStatus.failedWatcher provisioning failed.Inspect WatcherStatusPayload.status_reason; usually requires re-creating the watcher with corrected parameters.
WatcherEventStatus.archive_failedArchive teardown failed.Retry the archive PATCH; if it persists, contact support.
WalletStatus.failedSmart Account deploy failed.Inspect WalletStatusPayload.status_reason; provision a fresh wallet.
OperationStatus.failedOperation execution failed (revert, gas, …).Inspect OperationStatusPayload.status_reason; resubmit with corrected calldata.
OperationStatus.expiredDraft deadline elapsed before finalization.Create a new draft with a fresh wallet_operation_id. See Drafts.
QueryStatus.failedChain query execution failed.Inspect QueryError in the result; check contract address and calldata. See Chain Queries.
QueryStatus.expiredQuery TTL elapsed before terminal callback.Resubmit the query with a new idempotency key. See Chain Queries.

Subscribe to the appropriate *.status event stream to react to these transitions in real time. See Lifecycles.

Worked example

op, err := ext.PrepareRequestSubscriptionWithTokenApprovalOperation(
    fundAdminAddr, fundTokenId, amount, refID, paymentToken,
)
if err != nil { return fmt.Errorf("build op: %w", err) }

resp, err := client.Transact.ExecuteOperation(ctx, channelID, signer, op, chainSelector)
if err != nil {
    switch {
    case errors.Is(err, transact.ErrChannelNotFound):
        // bad channel id
    case errors.Is(err, eip712.ErrUnsupportedChainFamily):
        // unsupported chain
    default:
        return err
    }
}

See also

Get the latest Chainlink content straight to your inbox.