Skip to main content

Errors

milvusql.dbapi.errors owns the full PEP 249 exception hierarchy, and one function — translate() — mapping every upstream exception milvusql can hit onto it. Both the sync Cursor and the async aio client call it at every boundary with pymilvus/sqlglot, so the mapping lives once.

Why this matters

SQLAlchemy and Django both inspect the type of whatever a DBAPI raises to decide things like "is this connection dead, should the pool discard it." A foreign exception type (a bare pymilvus.exceptions.MilvusException, a raw grpc.RpcError) defeats that — translate() is what lets milvusql-sqlalchemy and milvusql-django get correct error handling for free, without either package needing its own mapping.

The hierarchy

Warning
Error
├── InterfaceError
└── DatabaseError
├── DataError
├── OperationalError
├── IntegrityError
├── InternalError
├── ProgrammingError
└── NotSupportedError

All importable from milvusql directly: milvusql.ProgrammingError, milvusql.OperationalError, etc.

What maps to what

UpstreamMapped toWhy
sqlglot.errors.ParseError / TokenErrorProgrammingErrorThe MilvusQL text itself is wrong
sqlglot.errors.UnsupportedErrorNotSupportedErrorWell-formed, but Milvus (or MilvusQL) can't do it
MilvusUnavailableException / ConnectErrorOperationalErrorNot reachable right now, not a bad request
CollectionNotExistException / IndexNotExistExceptionProgrammingErrorThe request names something that doesn't exist
SchemaNotReadyException / ParamErrorProgrammingErrorBad schema/parameters — also a request the caller got wrong
a plain MilvusException with ErrorCode.COLLECTION_NOT_FOUND (100) or ErrorCode.INDEX_NOT_FOUNDProgrammingErrorThe server reports "doesn't exist" this way too — confirmed directly, not just the typed subclass
a plain MilvusException mentioning "not loaded"ProgrammingErrorA collection isn't loaded — rare now that search/query/hybrid_search auto-LOAD on first use per connection (see Overview → Loading a collection), but still possible: a bare MilvusClient call outside this DBAPI can release a collection out from under a connection's cache, and auto-LOAD itself can fail this way too (no index yet, collection dropped concurrently)
any other MilvusExceptionDatabaseErrorGeneric fallback
grpc.RpcError with UNIMPLEMENTEDNotSupportedErrorSome RPCs aren't implemented on every server (Milvus Lite, notably)
grpc.RpcError with UNAVAILABLE/DEADLINE_EXCEEDEDOperationalErrorTransport-level connectivity failure

The last two rows exist because some failures happen at the gRPC transport layer before Milvus's own check_status() ever runs — they surface as a bare grpc.RpcError, not a MilvusException, a separate exception family translate() has to handle too.

Catching errors

import milvusql

try:
cur.execute("SELECT id FROM does_not_exist LIMIT 1")
except milvusql.ProgrammingError as exc:
print(f"bad query: {exc}")