Reference

Error reference

Every typed error the Extentos SDK can return — ConnectError, CaptureError, AudioError, TransportError, the ExtentosError umbrella, and the Meta-DAT DeviceSessionError — with their payload fields and meaning. Lifecycle operations return ExtentosResult<T, E> with these concrete failure variants rather than throwing; pattern-match them. Generated from the Rust core.

Generated from source. The error enums below are emitted from the Rust core (core/extentos-core/src/types/errors.rs), which is codegen'd into the Kotlin and Swift SDKs. The same variants exist on both platforms; Kotlin uses the PascalCase names shown, Swift the lowerCamelCase equivalents (TransportFailure.transportFailure).

How errors surface

Lifecycle operations don't throw — they return an ExtentosResult<S, F> with a typed failure variant. This is DAT's own convention and avoids coroutine-cancellation footguns. Pattern-match the result; don't wrap it in runCatching (which only catches thrown exceptions and would mask the typed error):

when (val r = glasses.camera.capturePhoto()) {
    is ExtentosResult.Ok  -> render(r.value)          // Photo
    is ExtentosResult.Err -> when (val e = r.error) {  // CaptureError
        is CaptureError.PermissionDenied -> requestCameraPermission()
        is CaptureError.ThermalCritical  -> toast("Glasses too hot — let them cool")
        is CaptureError.DisabledByUser   -> explainToggle(e.toggle)
        else                             -> log(e)
    }
}

Helpers on the Kotlin ExtentosResult: .map { }, .flatMap { }, .valueOrNull(), .errorOrNull().

The Swift shape differs in names, not model — ExtentosResult is .success(Success) / .failure(Failure), with map / flatMap and optional success / failure properties instead of valueOrNull() / errorOrNull():

switch await glasses.camera.capturePhoto() {
case .success(let photo): render(photo)
case .failure(let error): // CaptureError
    switch error {
    case .permissionDenied: requestCameraPermission()
    case .thermalCritical:  toast("Glasses too hot — let them cool")
    default:                log(error)
    }
}

The code + message carried by the PlatformError / TransportFailure variants is the shell's stable machine tag for a native-origin failure (the original native exception is logged to the event log at the catch site, not carried across the FFI).

Connection errors

ConnectError

Returned by glasses.connection.connect().

VariantPayloadMeaning
NoDeviceAvailableNo paired or otherwise known device is available to connect to.
PermissionDeniedA runtime permission required to connect was denied.
PairingFailedPairing / handshake with the device failed.
RegistrationRequiredThe install must register / authenticate before it can connect.
TransportFailurecode: String, message: StringA native transport-layer failure surfaced while connecting.

Capture errors

CaptureError

Returned by glasses.camera.capturePhoto() / captureVideo().

VariantPayloadMeaning
NotConnected
PermissionDenied
ThermalCritical
HingesClosed
CoexistenceBlocked
StreamPausedThe user paused the camera with the glasses' capture button (temple tap), so the live stream this capture needs is held, not flowing.
DisabledByUsertoggle: StringA user-facing toggle is gating this capture; toggle is the toggle key (e.g. camera_streaming_enabled) so a handler can explain it.
PlatformErrorcode: String, message: StringA native-origin capture failure — structured code + message.

Audio errors

AudioError

Returned by glasses.audio.recordDiscrete() / speak().

VariantPayloadMeaning
NotConnected
PermissionDenied
CoexistenceBlocked
DisabledByUsertoggle: StringAs CaptureError.DisabledByUser — a toggle (e.g. audio_capture_enabled).
PlatformErrorcode: String, message: String

Transport errors

TransportError

Surfaced by the underlying transport (simulator WebSocket or Meta DAT). WebsocketClosed.code is the WebSocket close code.

VariantPayloadMeaning
WebsocketClosedcode: i32, reason: Option&lt;String&gt;
HandshakeFailedreason: String
SchemaMismatchserver_version: String, client_version: String
Timeout
HardwareUnavailablereason: String
PlatformErrorcode: String, message: String

The umbrella type

ExtentosError

ExtentosError wraps the four per-area errors plus a catch-all, for APIs that surface any failure.

VariantPayloadMeaning
Connectinner: ConnectError
Captureinner: CaptureError
Audioinner: AudioError
Transportinner: TransportError
Unexpectedmessage: String

Meta DAT device-session errors

DeviceSessionError

Surfaced by the Meta DAT bridge (RealMetaTransport) when starting a device session on real hardware.

VariantPayloadMeaning
NoEligibleDevice
PlatformErrorcode: String, message: String

Assistant errors (Phase 4)

The Phase-4 assistant runtime (glasses.assistant.*) uses a shell-level AssistantError type (not a Rust core enum) with the same six variants on both platforms: a Kotlin sealed class thrown wrapped in AssistantException (com.extentos:glasses, since 1.4.0 — see SDK install) and a Swift AssistantError enum in GlassesCore (lowerCamelCase cases — .noApiKey, .providerError(code:message:)).

VariantPayloadMeaning
NoApiKeyThe Extentos managed gateway isn't reachable. Legacy name: there is no API key to supply — the assistant always runs on the managed gateway. Beta and production builds attest automatically (Play Integrity / App Attest) and need no setup. A sideloaded development build cannot attest, so it reaches the gateway one of two other ways — bound to a browser-simulator session, or through the dev-tier project-key lane. If you hit this on real hardware from a debug build, that binding is what's missing: see how the gateway identifies a caller.
AlreadyActiveAn assistant session is already active (the runtime is singleton-active).
SessionEndedstart() was called on a session that has already stopped.
NotReadywake / sleep / say / etc. called on an Idle or non-Active session.
NetworkErrorcause: ThrowableA network failure reaching the gateway or provider.
ProviderErrorcode, messageThe upstream AI provider returned an error.

There is no DisplayError

Display (glasses.display.*) has no returned error typeshow() degrades gracefully and never throws (a transport with no display path simply no-ops). Display delivery problems surface as runtime log events on glasses.runtime.events (display.video_delivery_failed, display.image_delivery_failed, display.video_error) and on the errors chip in the simulator event log (they are warn severity). See the display capability docs.