Skip to main content
VaultKit errors share a common base class and stable error code. Catch the base class for unified logging, or a subclass when retry behavior matters. NewtonShieldError remains as a compatibility alias, but new code should import ShieldError.
class ShieldError extends Error {
  readonly code: string
  readonly cause?: unknown
}

Error Classes

ErrorWhen it occursRetry safe?
PolicyDeniedErrorNewton operators evaluated the policy and denied the intent.No. Rebuild the action or accept the denial.
NewtonTaskEvaluationErrornewt_createTask failed or returned a malformed or negative evaluation result. Check the gateway result’s operator_errors[] before retrying.Depends. A retryable: false operator error is deterministic.
AttestationTimeoutErrorThe gateway did not return attestation data before the SDK timeout.Yes, with a fresh task.
GatewayErrorA gateway transport or envelope failure occurred.Usually yes, with backoff.
GatewayHttpErrorGateway returned a non-success HTTP response such as 401 or a surviving 5xx.Depends. Retry 5xx; fix auth or request issues for 4xx.
GatewayRpcErrorGateway returned a JSON-RPC error.Depends on the RPC code.
GatewayTimeoutErrorA gateway request timed out before a response arrived.Yes, with backoff.
ParamMismatchErrorAn existing Shield clone has policy params that do not match the expected params.No. Reconcile configuration manually.
PolicyMismatchErrorAn existing Shield clone is bound to a different policy than the selected pack expects.No. Verify the clone or deploy a new version slot.
ShieldExecutionErrorShield.execute, executeDirect, or executeBypass reverted.Depends on the decoded contract error.
InvalidConfigurationErrorCaller configuration is invalid before network or chain calls begin.No.
IntentConfigurationErrorIntent submission parameters are malformed.No.
IntentMismatchErrorDirect execution saw a task intent that differs from the task-response intent.No. Rebuild and re-attest.
ConcurrentIntentErrorAnother gated call is already in flight for the same clone.Yes, after the prior call settles.
ExtendCollisionErrorA vendor overlay would overwrite an existing client member.No.
TransactionFailedErrorA transaction failed outside the Shield-specific execution decode path.Depends on cause.
ShieldDeploymentNotFoundErrorA chain and environment are known, but the SDK has no Shield deployment recorded.Maybe. Try a different environment or wait for deployment.
UnsupportedChainErrorThe wallet client chain is not supported by VaultKit.No.

Decoded Contract Errors

When a Shield transaction reverts, the SDK decodes Shield custom errors and exposes them on ShieldExecutionError.decoded:
type DecodedContractError = {
  errorName: string
  args: readonly unknown[]
  rawData: `0x${string}`
}
Common onchain causes include InvalidAttestation, IntentMismatch, NotApprovedDelegate, IntentExecutionFailed, BypassNotReady, BypassUnknown, BypassAlreadyQueued, BypassDelayBelowMinimum, and target vault reverts.

Failed Task Diagnostics

NewtonTaskEvaluationError.message carries the gateway’s top-level summary, which can be less actionable than the operator-level detail. Always inspect the raw gateway result’s operator_errors[] before deciding a failure is transient. For example, a top-level “Quorum not reached” summary can still include a deterministic operator error such as:
{
  "message": "Policy evaluation failed: Failed to validate params schema: Missing required property 'vaultsfyi' at ''",
  "retryable": false
}
In that case, retrying will not help. The fix is to align the onchain composite params schema with the manifest envelope { "_manifest", "modules", "params" } and nest pack params under params.<short-id>.

Retry Pattern

import {
  AttestationTimeoutError,
  GatewayError,
  ShieldError,
} from '@newton-xyz/vaultkit'

async function retryable<T>(fn: () => Promise<T>, attempts = 3): Promise<T> {
  let lastError: unknown

  for (let i = 0; i < attempts; i++) {
    try {
      return await fn()
    } catch (error) {
      if (error instanceof AttestationTimeoutError || error instanceof GatewayError) {
        lastError = error
        await new Promise((resolve) => setTimeout(resolve, 1000 * 2 ** i))
        continue
      }

      throw error
    }
  }

  throw lastError
}

try {
  await retryable(() => shield.sendCall(args))
} catch (error) {
  if (error instanceof ShieldError) {
    console.error({ code: error.code, message: error.message, cause: error.cause })
  }

  throw error
}
Log code, message, and cause together. The code is stable enough for alerts; the cause is what engineers need for diagnosis.