Skip to main content

Exceptions

Neo4j error codes are converted to MikroORM's own exceptions, so catch blocks written against the ORM keep working across dialects:

ExceptionNeo4j error code
UniqueConstraintViolationExceptionNeo.ClientError.Schema.ConstraintValidationFailed
NotNullConstraintViolationExceptionNeo.ClientError.Schema.PropertyExistenceError
SyntaxErrorExceptionNeo.ClientError.Statement.SyntaxError
ReadOnlyExceptionNeo.ClientError.Statement.AccessMode (a write on a replica)
DeadlockExceptionNeo.TransientError.Transaction.DeadlockDetected
ConnectionExceptionNeo.TransientError.Network.ConnectivityError

A failing statement is logged at error level before the exception is converted and thrown, so it appears in the query log with its timing and parameters rather than only as a stack trace. See observability.

Errors raised before anything is sent​

The driver refuses what it cannot honour, rather than accepting it and doing nothing. Each of these throws locally, with a message naming the alternative:

SituationWhere it is documented
isolationLevel, explicit nested propagation, pessimistic lockModeTransactions
A SQL raw() / sql fragment in a filter (Neo4jRawFragmentError)Raw Cypher
An operator with no Cypher equivalent ($hasKey and friends)Query conditions
$fulltext nested in $or / $not, or two of them in one queryFull-text search
Two collection operators on one relationQuery conditions
Ordering by an unexpanded to-many relationQuery conditions
A partial (where) index, or type: 'vector'Indexes
A routine declaring body, language, security, or an output parameterStored routines
A write routine invoked on a read-only connectionStored routines
Why refuse rather than ignore?

An option that cannot be honoured must never appear to be honoured. A lockMode accepted and dropped is a caller believing rows are locked when they are not — the dangerous half of the pair, and the reason both entry points now throw.