Skip to main content

ErrorCode

Enum ErrorCode 

Source
#[non_exhaustive]
pub enum ErrorCode {
Show 38 variants CouldNotResolveAddr, InvalidApiCall, SocketError, ConnectTimeout, InvalidUtf8, InvalidName, InvalidTimestamp, AuthError, TlsError, HttpNotSupported, ServerFlushError, ConfigError, ArrayError, ProtocolVersionError, InvalidDecimal, ServerRejection, ArrowUnsupportedColumnKind, ArrowIngest, FailoverRetry, RoleMismatch, HandshakeError, UnsupportedServer, ProtocolError, InvalidBind, ServerSchemaMismatch, ServerParseError, ServerInternalError, ServerSecurityError, LimitExceeded, ServerLimitExceeded, Cancelled, FailoverWouldDuplicate, SchemaDrift, NoSchema, ArrowExport, BatchTooLarge, StoreResendRequired, SymbolDictFull,
}
Expand description

Category of error.

This is the single, unified error category for the whole client: it spans both ingestion (writing into QuestDB) and queries (reading out). Not every variant can arise from every operation — the ingest path never emits the reader-only wire/cursor categories, and a query never emits the sender-only encode categories — but a caller handling errors from a QuestDb pool, which spans both directions, sees one category enum.

Accessible via Error’s code method.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

CouldNotResolveAddr

The host, port, or interface was incorrect.

§

InvalidApiCall

Called methods in the wrong order. E.g. symbol after column.

§

SocketError

A network error connecting or flushing data out. Transient — obtain a fresh connection (or let the pool rotate) and retry.

The terminal, resend-required failure of the QWP/WebSocket store-and-forward persisted symbol dictionary is a distinct code, StoreResendRequired, so a caller can tell it apart from a retryable socket drop by code, without matching on the error message text.

§

ConnectTimeout

The TCP connect (dial) to the server exceeded the configured connect_timeout. Distinct from SocketError so a caller can tell a timed-out dial apart from a refused / reset connection. Currently produced only by the QWP/WebSocket transport.

§

InvalidUtf8

The string or symbol field is not encoded in valid UTF-8.

This error is reserved for the C and C++ API.

§

InvalidName

The table name or column name contains bad characters.

§

InvalidTimestamp

The supplied timestamp is invalid.

§

AuthError

Error during the authentication process.

§

TlsError

Error during TLS handshake.

§

HttpNotSupported

The server does not support ILP-over-HTTP.

§

ServerFlushError

Error sent back from the server during flush.

§

ConfigError

Bad configuration.

§

ArrayError

There was an error serializing an array.

§

ProtocolVersionError

Validate protocol version error.

§

InvalidDecimal

The supplied decimal is invalid.

§

ServerRejection

QWP/WebSocket server rejection or terminal protocol violation.

§

ArrowUnsupportedColumnKind

PooledSenderCore::flush_arrow_batch_* was passed a column whose Arrow / QuestDB kind cannot be persisted to a QuestDB table (e.g. ARRAY(LONG, N-D) is query-result-only on the egress side and has no QWP wire tag for ingress). Only emitted on the arrow feature.

§

ArrowIngest

PooledSenderCore::flush_arrow_batch_* was passed a RecordBatch that failed client-side structural validation (column count vs schema, name encoding, ARROW C Data Interface invariants on a freshly imported array, etc.). Only emitted on the arrow feature.

§

FailoverRetry

A reconnectable failure on the column-major sender’s flush/sync path (transport error, EOF, or a closed connection). The operation has not committed; the caller should obtain a fresh connection from the pool (which rotates to a live endpoint) and re-drive from its source. Distinct from terminal failures (auth / protocol / schema / server rejection), which must not be retried.

§

RoleMismatch

Every reachable endpoint completed its handshake but none advertised a role matching the configured target= filter (e.g. target=primary against an all-replica address list, or a 421 + X-QuestDB-Role: REPLICA upgrade reject). Distinct from SocketError (“all endpoints unreachable”) so callers can tell “no primary elected yet” from “everything is down”.

§

HandshakeError

HTTP-upgrade or WebSocket handshake failure.

§

UnsupportedServer

Server returned an unsupported QWP version, encoding, or capability.

§

ProtocolError

Wire-format violation: bad magic, truncated frame, unknown discriminant, invalid varint, symbol-dict reference miss, etc.

§

InvalidBind

Bind parameter index, count, or value rejected client-side (before the QUERY_REQUEST hits the wire). On the query path this covers timestamp / decimal / geohash range failures alongside everything else caught at bind time.

§

ServerSchemaMismatch

Server-reported QWP SCHEMA_MISMATCH (status 0x03).

§

ServerParseError

Server-reported QWP PARSE_ERROR (status 0x05).

§

ServerInternalError

Server-reported QWP INTERNAL_ERROR (status 0x06).

§

ServerSecurityError

Server-reported QWP SECURITY_ERROR (status 0x08).

§

LimitExceeded

Client-side limit hit (e.g. an array row exceeds the configured per-row element cap).

§

ServerLimitExceeded

Server-reported QWP LIMIT_EXCEEDED (status 0x0B).

§

Cancelled

Query was cancelled (locally or via server CANCELLED status 0x0A).

§

FailoverWouldDuplicate

Mid-query failover was eligible but at least one batch had already been delivered to the caller, and the cursor’s on_failover_reset callback was not installed. Failover would replay the query from the start on the new endpoint, re-delivering already-consumed rows, so the cursor terminates with this error instead of silently duplicating. The caller must install on_failover_reset (and discard partial state on each invocation) or re-run the query from scratch.

§

SchemaDrift

Streaming Arrow adapter saw a mid-stream schema change: a later RESULT_BATCH decoded into an Arrow schema that differs from the snapshot captured at adapter construction. The adapter is poisoned; the underlying cursor remains usable and the caller may re-wrap it with a fresh as_arrow_reader() call. Only emitted on the arrow feature.

§

NoSchema

Cursor::as_arrow_reader() was called on a stream that terminated before any RESULT_BATCH was decoded — there is no schema to snapshot. Recoverable: treat as a “no rows” result, or re-execute. Only emitted on the arrow feature.

§

ArrowExport

Arrow C Data Interface export failed (e.g. arrow-rs rejected an internal invariant on the produced ArrayData). Indicates a crate bug; not user-recoverable. Only emitted on the arrow feature.

§

BatchTooLarge

An irreducible QWP/WebSocket unit (the table schema plus a single row block) exceeds the negotiated per-batch cap (min(max_buf_size, server X-QWP-Max-Batch-Size)). Chunk publication splits oversize inputs into smaller frames automatically, so this only surfaces when splitting cannot make a frame fit. Distinct from InvalidApiCall so callers can recognise it without matching on the error message text.

§

StoreResendRequired

The QWP/WebSocket store-and-forward persisted symbol dictionary is unrecoverable, so the queued frames that reference it cannot be replayed: a host/power crash tore the .symbol-dict side-file relative to the queued frames, or it could not be written ahead of them. Retrying the connection will not help — the affected rows must be re-ingested from their source.

Terminal, and distinct from SocketError (a transient, retryable socket drop) so a caller can tell “resend from source” apart from “reconnect and retry” by code, without matching on the error message text. The sender’s own reconnect/failover loops treat it as terminal (they stop) rather than retrying it to their deadline.

§

SymbolDictFull

The QWP/WebSocket connection-scoped symbol dictionary is full: interning another distinct symbol would push it past its entry-count cap (2,000,000, matching the server’s ingress ceiling) or its cumulative UTF-8 heap cap (256 MiB). The dictionary accumulates every distinct symbol referenced across every column, chunk, and row-buffer flush on one connection, and is only reset by discarding that connection.

The failing frame is rejected before any byte reaches the wire and the buffer is rolled back, so that flush loses nothing and already-interned symbols keep flushing — but retrying a new symbol on the same sender can never succeed. A full dictionary therefore retires the connection on return: a pooled sender is dropped rather than recycled (so the next borrow gets a fresh, empty-dictionary connection, not the same full one), and the frames flushed earlier on it are drained / committed best-effort on the way out. So the simplest recovery is to return or drop the sender as usual and continue on a fresh borrow. If those earlier frames must not be lost, drain or commit them and check first, as below.

  • Pooled row sender (QuestDb::borrow_sender): a full dictionary marks the connection for retirement, so a plain drop (which is the pool return) drains the queue best-effort within close_flush_timeout and drops the connection instead of recycling it — the next borrow gets a fresh one. (Nothing extra to call: an explicit drop_on_return() does the same and is redundant here.) wait() first if the queued frames must not be lost. With sf_dir configured they persist in the slot, but so does the dictionary, and the next borrower re-seeds from that slot’s side-file at the same size unless the slot drained first — so wait() there too, so the slot drains and the next borrower starts clean.
  • Pooled direct column sender (QuestDb::borrow_direct_column_sender): a full dictionary marks the connection spent — retired on return, but its transport is healthy and still drainable — so a plain drop commits the deferred tail best-effort and retires the connection. Its flush is deferred (nothing is committed until commit or flush_and_wait), so for a checked guarantee call commit(..) (or flush_and_wait(..) on the final chunk) and confirm it succeeded before the drop — commit still goes through on a spent connection. Do not reach for drop_on_return() on a full dictionary: it hard-latches the connection, which makes the drop skip the best-effort commit and discard the tail. reborrow_from_pool() likewise discards the in-flight tail (its failover contract), so commit/wait() before it if that tail matters.
  • Standalone (Sender): call close_drain and check it succeeded, then drop and reconnect. Unlike the pooled guards above, a plain drop drains nothing here — SyncProtocolHandler’s Drop shuts down the ILP-over-TCP socket and has no QWP/WebSocket arm at all, so every published-but-unacked frame is discarded with no wait. This is the most lossy of the three flavours on a bare drop, not the least. close_drain is bounded by close_flush_timeout.
  • C ABI: a plain questdb_db_return_sender / questdb_db_return_direct_sender now retires (does not recycle) a full-dictionary connection and drains / commits its pending frames best-effort — call qwp_sender_wait / qwp_direct_sender_commit first for a checked guarantee. questdb_db_drop_direct_sender force-drops and skips the direct sender’s tail commit, so on a full dictionary prefer the plain return unless you mean to discard the tail.

One exception to “that flush loses nothing”, and it matters for resends. A chunk too large for a single frame is split, and each half is published on its own; store-and-forward is at-least-once, so an earlier half can already be durably queued when a later half hits the cap. Nothing is lost then either, but the operation is no longer known-not-delivered: it is reported as delivery-unknown, so check in_doubt before resending — a blind resend of the whole chunk duplicates the rows the committed prefix already carried.

Distinct from InvalidApiCall — a caller mistake with no recovery — so callers can recognise a full dictionary by code and take that specific action, without matching on the error message text.

Trait Implementations§

Source§

impl Clone for ErrorCode

Source§

fn clone(&self) -> ErrorCode

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for ErrorCode

Source§

impl Debug for ErrorCode

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for ErrorCode

Source§

impl Hash for ErrorCode

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for ErrorCode

Source§

fn eq(&self, other: &ErrorCode) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ErrorCode

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Key for T
where T: Clone,

Source§

fn align() -> usize

The alignment necessary for the key. Must return a power of two.
Source§

fn size(&self) -> usize

The size of the key in bytes.
Source§

unsafe fn init(&self, ptr: *mut u8)

Initialize the key in the given memory location. Read more
Source§

unsafe fn get<'a>(ptr: *const u8) -> &'a T

Get a reference to the key from the given memory location. Read more
Source§

unsafe fn drop_in_place(ptr: *mut u8)

Drop the key in place. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V