Errors

Error surface

The SDK exposes typed errors at two levels. DvmBridgeError comes from DvmClient operations. MobileNodeError comes from DvmMobileNode direct calls. Both map to clear recovery paths.

Use the error kind and message as product state. The kind indicates which recovery path to take; the message carries context to correlate with logs.

The reason-code table below is a different layer: the typed SDK errors here are the local surface a caller catches, while the runtime reason codes (POLICY_DENIED, REMOTE_TIMEOUT, PUBLICATION_DENIED, and more) are the runtime causes carried in receipts and logs.

Reason-code registry

Failure states

Reason codes align SDK errors, runtime receipts, retry policy, evidence artifacts, and operator action.

POLICY_DENIEDPolicy admission
Client state

Denied

Retry policy

Do not retry until approval, limit, or display binding changes.

Evidence artifact

AdmissionDecision, policy hash, denial reason

Operator action

Route to approval owner or product policy review.

REMOTE_TIMEOUTProtocol plane
Client state

PendingRemote

Retry policy

Resume with the same operation id and participant set.

Evidence artifact

Peer wait record, deadline, last valid ingress hash

Operator action

Check peer delivery, relay health, and participant availability.

STEP_PERMIT_REUSEDSecret kernel
Client state

Failed

Retry policy

Do not retry the local step; abort or rotate the session.

Evidence artifact

PermitEvent, local artifact state, request digest

Operator action

Quarantine local artifact and investigate replay or duplicate execution.

PUBLICATION_DENIEDPublication gate
Client state

Executed

Retry policy

Retry publication only after publication policy changes.

Evidence artifact

PublicationReceipt denial, disclosure scope, result reference

Operator action

Keep local result closed and route to publication approver.

EQUIVOCATIONValidated ingress
Client state

Failed

Retry policy

Do not retry the conflicting operation.

Evidence artifact

Both signed peer facts, slot, sender, session id

Operator action

Escalate peer conflict and preserve the evidence bundle.

BOUNDARY_UNAVAILABLELocal signer boundary
Client state

Unavailable

Retry policy

Retry only after runtime, JNI, HSM, or vault health is restored.

Evidence artifact

Boundary health state, call id, platform error kind

Operator action

Fix local runtime packaging, vault access, or HSM availability.

Client-level errors (DvmBridgeError)

policyRejected(reason) fires when DvmPolicyProvider.evaluate returns approved: false. Treat it as product state: record the rejection reason for support, gate retry on a policy change rather than on time, and never retry it automatically without a state change. unsupported(reason) fires on designed-but-not-yet-wired calls — currently backups.recover(), backups.rotateCredential(), operations.cancel(), and operations.resume().

unavailable(message) indicates the bridge is not open or has shut down. ffi(code:message:) is a native runtime error; the code is a stable Rust error key suitable for log correlation. invalidIdentifier(message) fires on malformed operation or key id values.

Signer-level errors (MobileNodeError)

unavailable usually points to native library loading or platform packaging. ffi points to a native runtime error from the Rust side. invalidResponse points to an ABI shape mismatch between the Swift wrapper and the native library version. bindingMismatch points to a result that belongs to different public facts than what the binding expected. storage points to vault path or keyshare file availability.

Show packaging and availability problems as service health states; they are infrastructure failures. Show storage problems as key recovery or re-enrollment flows. Treat bindingMismatch as a security-relevant event: persist the public context (error kind, operation id, key id, public key) for investigation. Route bindingMismatch and production eligibility failures to release gates instead of retrying.