Skip to main content

Errors and diagnostics

Softchat failures are stable, typed, and redacted. Rust uses enum variants; the authored facades expose one idiomatic error value with one stable code. Branch on that variant or code, never display text, a generated-binding exception, relay prose, or an upstream cryptographic error.

The Android account runtime also emits optional structured diagnostics with English summaries, TX/RX direction, authenticated subject, source timestamps, and bounded counters. The account logging contract defines the event catalog, committed milestones, privacy rules, and volume limits. Logs support diagnosis; commands and queries remain the source of product state.

Handling failures

Operation contracterrors.handling

Handle stable redacted failures without generated-binding leakage.

Inputs and exact bounds
  • one SDK operation failure
Output
One idiomatic error value and stable code.
Trust and authentication
Display text is safe but not a branching contract.
Stable errors
internal_failure · handling and retry rules
Ownership, lifecycle, and execution rules
Ownership
Rust owns protocol semantics, Android account SQLite/use-case state, and optional native relay I/O; the host owns account lifecycle, HTTP/media/background effects, files, and UI.
Retry
Retry only host transport or explicitly retryable session work; validation and authentication failures are permanent for the same input.
Lifecycle
Language ownership is automatic; explicitly cancel or erase only at the operation-specific authority boundary.
Concurrency
Serialize mutable session capabilities; immutable values follow the language type system.
Cancellation
The host owns async cancellation; use cancel, shutdown, close, or erase only where exposed.
Exact public symbols
SoftchatError
match bob.decrypt_utf8(&message) {
Ok(plaintext) => display(plaintext),
Err(SoftchatError::DecryptionFailed) => discard_untrusted_message(),
Err(SoftchatError::IdentityErased) => require_reauthentication(),
Err(error) => record_code(error.code()),
}

Retry categories

FailureTypical action
malformed, invalid, oversized, unsupportedpermanent rejection of that input
authentication/decryption failurediscard untrusted value; do not reveal details
erased/closed/cancelled statecreate a new authority or state object when policy permits
relay retryable deliverypersist and retry under the session’s requested policy
internal failurerecord only build fingerprint, stable code, and safe host context

Build fingerprint

Operation contractdiagnostics.snapshot

Identify the loaded artifact and inspect redacted counters.

Inputs and exact bounds
  • no protocol payload input
Output
Build fingerprint and monotonic redacted counters.
Trust and authentication
Diagnostics contain no keys, plaintext, ciphertext, or event contents.
Stable errors
internal_failure · handling and retry rules
Ownership, lifecycle, and execution rules
Ownership
Rust owns protocol semantics, Android account SQLite/use-case state, and optional native relay I/O; the host owns account lifecycle, HTTP/media/background effects, files, and UI.
Retry
Retry only host transport or explicitly retryable session work; validation and authentication failures are permanent for the same input.
Lifecycle
Language ownership is automatic; explicitly cancel or erase only at the operation-specific authority boundary.
Concurrency
Serialize mutable session capabilities; immutable values follow the language type system.
Cancellation
The host owns async cancellation; use cancel, shutdown, close, or erase only where exposed.
Exact public symbols
build_fingerprintdiagnostics_snapshot

The build fingerprint identifies the semantic version, source revision, protocol profile, target architecture, and target operating system. Include it with a bug report to distinguish package skew without logging account data.

let fingerprint = build_fingerprint();

Diagnostics snapshot

The process-local snapshot reports aggregate operation counts, rejected operations, and input/output bytes. It deliberately excludes keys, plaintext, ciphertext, URLs, relay frames, event content, and identifiers.

let counters = diagnostics_snapshot();

Diagnostics are counters, not an audit trail. If an application needs operation correlation, generate its own non-secret trace ID outside the SDK.