Skip to content

Errors

The public Kairos thin client surfaces a single error enum, kairos::LinkError. It is the safe mirror of the engine's C-ABI KAIROS_ERR_* status codes plus the wire-codec errors. Every fallible operation on the public surface returns Result<_, LinkError>; the public API delivers no panics under correct caller usage.

LinkError is #[non_exhaustive]; downstream match arms include a catchall _. New variants land as additive changes.

LinkError

VariantMeaning
LinkError::UnknownAnalytic(String)The analytic id is not registered with the engine. Mirrors the C KAIROS_ERR_UNKNOWN_ANALYTIC status.
LinkError::NoLiveEntry(String)The analytic has no live / streaming entry point (a cache-dependent analytic whose spec cannot be rebuilt from scalar wire params). Mirrors the C KAIROS_ERR_NO_LIVE_ENTRY status.
LinkError::Decode { analytic, detail }The engine rejected the encoded params blob (or an enum discriminant like wait_strategy). Mirrors the C KAIROS_ERR_DECODE status.
LinkError::NullArg { analytic, detail }The engine reported a NULL pointer / bad-argument on a call. Mirrors the C KAIROS_ERR_NULL_ARG status. Indicates a client-side bug; the public client should never trigger it.
LinkError::Engine { analytic, detail }The engine run / subscribe / connect failed (generic non-OK status — e.g. KAIROS_ERR_RUN, KAIROS_ERR_CONNECT, KAIROS_ERR_BUFFER_TOO_SMALL).
LinkError::HistoricalUnwired(String)The historical-over-C-ABI path is a documented follow-up and is not yet wired. Mirrors the C KAIROS_ERR_HISTORICAL_UNWIRED status. Surfaces from the preview client.historical(start, end) namespace.
LinkError::Encode(CodecError)A wire-params encode failed before the call reached the engine.
LinkError::Dropped { dropped_since_last_poll, detail }The engine's per-subscription outbound buffer overflowed since the last successful poll and one or more Arrow IPC batches were dropped — never silently swallowed. Mirrors the C KAIROS_ERR_DROPPED status.

The Dropped variant carries the exact number of frames missed since the previous successful poll. The consumer is behind the producer; catch up by polling more aggressively or abort the subscription. The next poll returns the new head batch normally.

Surfaces

The same LinkError enum reaches the caller through multiple surfaces, depending on where the failure was detected:

  • Client::connect — connect-time failures (upstream authentication, engine handshake).
  • AnalyticBuilder::on_event — subscribe-time failures (unknown analytic, no live entry, decode). The error surfaces before any row is delivered.

Once a subscription is live, a callback consumer has no per-row error channel — the documented surface is typed rows. A structural fault after subscribe (a stream fault, or the consumer falling far enough behind that the live buffer overflows) ends the subscription and marks its handle inactive rather than surfacing an error variant to the callback.

Convention

Every variant carries enough context to act on without rerunning the failing call: analytic id, codec detail, dropped-frame count. The crate does not ship opaque Internal variants — every failure mode is named.

Binding-side typed errors

The Python and TypeScript bindings add one error class beyond the core LinkError surface:

  • StreamPollContention (Python kairos_thetadata. StreamPollContention exception subclassing KairosError; TypeScript [StreamPollContention] … napi::Error reason prefix). Raised when a concurrent __anext__() / subscription.next() call arrives while a previous poll on the same live stream is still in flight. The async-iter contract is single-consumer per stream; clone the Client and open a second subscription if you need per-task fan-out. The error message carries the stream handle id so log analysis can identify the originating subscription. Without the typed error the racing call would silently observe end-of-iteration and drop every subsequent tick.

Proprietary. All rights reserved.