Error handling
Generated operations return rent::runtime::EntityError. Preserve the source with ? unless the application can
take a specific recovery action.
use rent::runtime::EntityError;
match client.user().email_eq(email).only().await {
Ok(user) => show_profile(user),
Err(EntityError::NotFound { .. }) => show_missing_profile(),
Err(error) => return Err(error.into()),
}Query and mutation invariants
| Error | Meaning | Typical response |
|---|---|---|
NotFound | only() found no row | Return absence or a domain-level not-found error |
NotSingular | only() found several rows | Fix the uniqueness or filter invariant |
MissingRequiredField | A create omitted required data | Fix request validation or builder construction |
InvalidConflictTarget | An upsert target is empty or unavailable | Use a matching unique field or tuple |
InvalidPageSize | A keyset page requested zero rows | Reject or clamp the input |
InvalidCursor | A cursor is malformed or belongs to another key | Return an invalid-pagination response |
InvalidStreamBatchSize | A stream requested an empty batch | Choose a positive bounded batch |
SingleTargetRequired | A one-row operation has no explicit target | Use *_one(&entity) or .one(id) |
InvalidCursorOrdering | Cursor pagination was combined with a conflicting order or an offset | Remove the order or offset, or choose a matching cursor |
InvalidEagerBatch | A relationship load cannot be split within the database parameter budget | Load fewer parents per query or narrow the window |
InvalidExtensionValue | A generated extension field rejected an invalid typed value | Validate the value before building the mutation |
MissingGeneratedId | The backend did not return the generated identifier needed to reload a created entity | Check the identity column and backend configuration |
Builder | SQL builder validation failed before execution | Fix the query shape the wrapped BuilderError names |
FastPathMiddleware | A raw high-throughput path such as COPY cannot preserve configured policies, hooks, or codecs | Use the ordinary builders for that entity |
Model accessors such as post.author()? return a separate RelationNotLoaded error, not an EntityError, when the
relationship was not eagerly loaded. Add the corresponding with_* call to the query.
Concurrency and transactions
OptimisticLock is an expected concurrency outcome: reload, merge, and retry only when the application's semantics
allow it. VersionOverflow indicates an invalid long-lived version counter and should be treated as an invariant
failure.
TransactionClosed, TransactionAlreadyActive, and TransactionsUnsupported report lifecycle misuse.
TransactionRollback preserves both the operation error and rollback failure so neither is lost.
TransactionError<E> is used when a transaction closure returns an application-defined error. Its variants keep
database and application failures distinct.
Driver and middleware errors
Driver wraps SQLx transport, server, decoding, cancellation, configuration, and argument errors. Check
is_retryable_transaction() only around a complete idempotent transaction; do not retry arbitrary statements after
an unknown partial outcome.
Policy, Intercept, and Hook identify the middleware layer that rejected an operation. FieldCodec identifies
the entity, field, and encode/decode direction for encryption, blob, or custom storage failures.
NativeProjection identifies the model when a native selected value cannot be decoded. Inspect its source for
the column/type mismatch, and check the schema against the live database. Retrying does not fix incompatible
storage types. Dynamic projection decoding reports Decode or InvalidProjection instead.
Migration and extension commands expose their own typed plan, inspection, apply, directory, and registry errors. Their CLI messages include the failing file, object, extension, or operation whenever it is known.