Skip to main content

DjogiError

Enum DjogiError 

Source
#[non_exhaustive]
pub enum DjogiError {
Show 41 variants Auth(AuthError), Db(DbError),
#[non_exhaustive]
NotFound { table: &'static str, },
#[non_exhaustive]
MultipleObjects { table: &'static str, count_seen: usize, }, IdGeneration(IdGenerationError),
#[non_exhaustive]
RelationUnloaded { model: &'static str, field: &'static str, }, Serde(Error), Visage(VisageError),
#[non_exhaustive]
GoneAggregate { model: &'static str, id: String, reason: &'static str, }, Decode(String),
#[non_exhaustive]
MissingIdempotencyKey { model: &'static str, }, Validation(String), LockConflict(DbError), StreamOutsideTransaction,
#[non_exhaustive]
TransactionPoisoned { reason: &'static str, },
#[non_exhaustive]
SessionStatementDisallowedInTransaction { statement: &'static str, },
#[non_exhaustive]
RawTransactionControlDisallowedInTransaction { statement: &'static str, },
#[non_exhaustive]
UnsupportedAggregate { op: &'static str, reason: &'static str, },
#[non_exhaustive]
InvalidSubqueryModifier { op: &'static str, reason: &'static str, }, AliasCollision { alias: String, },
#[non_exhaustive]
PoolTimeout { phase: &'static str, }, SetRoleOutsideTransaction, InvalidRoleName(String), Predicate(PortablePredicateError),
#[non_exhaustive]
SetOpArmInvalid { table: &'static str, side: &'static str, reason: &'static str, },
#[non_exhaustive]
SetOpOuterOrderingInvalid { table: &'static str, reason: &'static str, }, IsolationLevelOnNestedScope { requested: IsolationLevel, }, ConstraintModeOutsideTransaction, UnknownConstraintName(String), ConstraintNotDeferrable(String), EmptyDeferConstraintsScope, ConflictingDeferrabilitySpec { model_type_name: String, field_name: String, first: (bool, bool), second: (bool, bool), }, OrphanDeferrabilitySpec { model_type_name: String, field_name: String, }, DuplicateConstraintName { constraint_name: String, first_model: String, first_field: String, second_model: String, second_field: String, }, ConcurrentReadsRequirePoolContext,
#[non_exhaustive]
MergeSourceInvalid { table: &'static str, reason: &'static str, },
#[non_exhaustive]
MergeBranchInvalid { table: &'static str, reason: String, },
#[non_exhaustive]
MergeNoBranches { table: &'static str, reason: String, }, PresentationStartup(Vec<PresentationStartupError>),
#[non_exhaustive]
UnsupportedPostgresVersion { detected_major: u32, detected_minor: u32, minimum_major: u32, },
#[non_exhaustive]
StalePhaseZeroStatement { refusal_reason: &'static str, statement: String, },
}
Expand description

The single error type returned by every Djogi CRUD operation. Every fallible call site in djogi (Model::create, QuerySet::fetch_all, transaction::atomic, DjogiContext::set_tenant, every raw escape hatch, every spatial / FTS / JSONB helper) returns Result<T, DjogiError>. The crate-scoped crate::Result<T> alias spells exactly that — adopter code signs functions with -> djogi::Result<T> and uses ? to propagate.

§Error taxonomy

DjogiError groups failures by where they originate, not by HTTP-style status code. The most common branches:

  • Database-driver errorsDb wraps every tokio_postgres::Error (network, constraints, syntax, auth) behind the DbError facade so this enum does not leak tokio_postgres types.
  • Expected-row-count violationsNotFound for zero rows from Model::get / QuerySet::fetch_one, MultipleObjects for >1 row from fetch_one. Both carry the offending table name.
  • Concurrency / contentionLockConflict for 40001 / 40P01 / 55P03 SQLSTATE classes (serialization failures, deadlocks, NOWAIT rejections), PoolTimeout for deadpool checkout exhaustion. Both classify as transient — see DjogiError::is_transient.
  • Auth / RLSAuth wraps AuthError for authentication / authorization failures from the auth substrate; SetRoleOutsideTransaction and InvalidRoleName surface RLS- overlay misuse.
  • Misuse / runtime invariants Validation for runtime argument validation failures, MissingIdempotencyKey for upsert-attribute gaps, StreamOutsideTransaction for cursor / QuerySet::stream outside atomic, UnsupportedAggregate for IR / Postgres aggregate mismatches.
  • Decode / serializationDecode for FromPgRow failures, Serde for outbox JSON serialization, Visage for visage-projection TryFrom<&Model> failures.
  • ID generationIdGeneration wraps HeeRanjID-side codec failures.
  • Aggregate lifecycleGoneAggregate for terminal “already gone” signals on a previously-observed aggregate; RelationUnloaded for prefetch-cache misses on a strict-mode resolved-relation accessor.
  • SpatialGeo (gated on the spatial feature) wraps coordinate / EWKB codec errors.

§Retry classification

DjogiError::is_transient returns true for LockConflict, PoolTimeout, and the small set of variants whose failures are expected to be retryable. The framework also recognises the SQLSTATE classes that indicate contention vs. other database failures — both classifications are intended for use in caller-side retry policies (see also retry_on_conflict).

§#[non_exhaustive]

Both DjogiError and its struct-form variants (NotFound, MultipleObjects, RelationUnloaded, GoneAggregate, MissingIdempotencyKey, UnsupportedAggregate, PoolTimeout, InvalidRoleName, etc.) are #[non_exhaustive]. Downstream match expressions MUST include a wildcard arm, and downstream destructuring MUST use .. — adding a new variant or new field to a struct variant is therefore a non-breaking change. The cost is one extra wildcard arm at every match site; the benefit is the framework can grow new failure shapes (added a half-dozen) without breaking adopter code. Construction from outside this crate is also blocked by the variant-level #[non_exhaustive]. Use the public constructors (DjogiError::not_found, DjogiError::multiple_objects, etc.) when surfacing a Djogi-flavoured error from adopter code; this matches the pattern set by std::io::Error, hyper::Error, and similar well-designed error types.

§Why one error type

Every framework call returning Result<T, DjogiError> keeps ? propagation ergonomic across CRUD, raw SQL, transactions, auth, and spatial/JSONB layers. Per-subsystem error types would force adopter code into manual conversion at every layer boundary — exactly the friction that drove the framework’s “one error type at the public API” design.

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.
§

Auth(AuthError)

Authentication or authorization failure bubbled up through the auth substrate. Wraps AuthError so DjogiAuth::authenticate and DjogiAuth::verify failures flow through ? inside atomic()-managed operations without explicit mapping.

§Transitivity

Because AuthError is #[non_exhaustive], this variant also inherits that forward-compatibility contract at the DjogiError level: a match on DjogiError::Auth(e) that then matches on e must still include a wildcard arm for AuthError.

§

Db(DbError)

Raw database or driver error.

§

#[non_exhaustive]
NotFound

Model::get / QuerySet::fetch_one saw zero rows. The table field records the SQL table that was queried so log lines and error reports remain meaningful once errors propagate far from the call site.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§table: &'static str
§

#[non_exhaustive]
MultipleObjects

QuerySet::fetch_one (or similar) saw more than one row when exactly one was expected. count_seen is the number actually observed — with the LIMIT 2 strategy this is always exactly 2, but storing the real count keeps the error meaningful for future code paths that may pre-count rows differently.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§table: &'static str
§count_seen: usize
§

IdGeneration(IdGenerationError)

ID generation failed.

§

#[non_exhaustive]
RelationUnloaded

A relation accessor that requires an eagerly-loaded cache (ForeignKeyResolved::expect_resolved / OneToOneFieldResolved::expect_resolved) was invoked against a wrapper whose cache is empty. The caller asserted a prefetch() / select_related() ran earlier but none did — this is a strict-mode user error, not a query failure. model is the source model name (e.g. "Vehicle"), field is the relation field on that model (e.g. "owner_id"). Both are compile-time &'static strs — the macro fills them in from the struct definition in . Until then, callers supply them at the call site.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§model: &'static str
§field: &'static str
§

Serde(Error)

JSON serialization / deserialization failed. Raised by the Task 6 transactional-outbox emitter when serde_json::to_value cannot lower a model row into a JSON document — typically because a user field’s Serialize impl returned an error. Wraps the serde_json::Error verbatim so the caller can inspect the underlying failure.

§

Visage(VisageError)

Visage projection failure — raised when a TryFrom<&Model> impl on a generated visage cannot convert the row. Known triggers include VisageError::UnresolvedRelation, raised when a relation-nesting visage is projected from a model whose relation fields were not prefetch()-ed or select_related()-ed, and VisageError::PresentationCodec from fallible protected-field presentation codecs. Introduces this variant so the visage-scoped reverse-FK / M2M accessors can flow a fallible peer-visage conversion through ? without losing the VisageError structure. The #[from] shorthand on the inner type produces the impl From<VisageError> for DjogiError conversion the emitted accessors rely on.

§

#[non_exhaustive]
GoneAggregate

A DDD-style aggregate was hard-deleted mid-operation, invalidating any further work against its id. Task 7.7 introduces this variant as the canonical terminal signal for “the aggregate you’re operating on no longer exists” distinct from NotFound (which covers initial-lookup misses) in that the caller already observed the aggregate earlier in the same operation. model is the owning model’s type_name (same source as MissingIdempotencyKey::model). id is the PK rendered to a string (no generic parameter so the error type stays object-safe and usable across model boundaries). reason is a &'static str describing why the aggregate is gone (e.g. "hard-deleted by admin", "retention policy evicted"). Classified as terminal by DjogiError::is_transientretry_on_conflict does not retry this variant because retrying against a deleted row cannot succeed.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§model: &'static str
§reason: &'static str
§

Decode(String)

A column decode failure produced by FromPgRow::from_pg_row. Raised when tokio_postgres::Row::try_get returns an error for a model field — for example, when the wire type at a given ordinal position cannot be converted to the expected Rust type. Preserves the contract: every CRUD failure flows through DjogiError rather than aborting the task via panic!. The inner String carries the column name and the driver error so the caller can identify which field failed without inspecting the raw tokio_postgres::Error.

§

#[non_exhaustive]
MissingIdempotencyKey

A convenience method that consumes the descriptor’s idempotency_key slot (create_or_find / bulk_upsert_by_descriptor) was invoked against a model whose #[model(...)] attribute does not set the key. Task 7.5 introduces this variant as the runtime pointer at the attribute the caller needs to add. model is the type_name from [ModelDescriptor::type_name] a &'static str the macro lifts directly from the struct identifier.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§model: &'static str
§

Validation(String)

A runtime argument-validation failure produced by a CRUD convenience method — the caller’s request is well-typed at compile time but fails a runtime invariant (e.g. bulk_upsert’s conflict_cols naming a column that does not exist on the model). Task 7d introduces this variant for bulk_upsert’s allow-list check; future phases may add more callers. The inner String is a human-readable description of the failure. No &'static str because callers interpolate the offending column name / table name into the message.

§

LockConflict(DbError)

A FOR UPDATE NOWAIT / FOR UPDATE request could not acquire its row lock, or a SERIALIZABLE / REPEATABLE READ transaction encountered a serialization failure, or Postgres detected a deadlock and aborted one participant. introduces this variant so the retry helper (retry_on_conflict) and the caller can branch on lock-contention vs other database errors. Retryable SQLSTATE classes carried here:

  • 40001serialization_failure
  • 40P01deadlock_detected
  • 55P03lock_not_available (NOWAIT rejection) Other database failures — unique_violation, foreign_key_violation, connection drops — still flow through Db. The classifier [is_lock_error] keeps the variant boundary tight.
§

StreamOutsideTransaction

QuerySet::stream or DjogiContext::raw_stream was called on a pool-backed context (i.e. outside an atomic() scope). Postgres named cursors are transaction-local — they require an open transaction to exist. Calling stream on a pool-backed context is a caller error that is detected at stream construction time, not at the first poll_next. This makes the error surface immediate and actionable rather than deferred to the first row consume. Fix: wrap the stream consumer in atomic(&mut ctx, |ctx| Box::pin(async move { … })) so ctx is transaction-backed when stream is called.

§

#[non_exhaustive]
TransactionPoisoned

A transaction-backed crate::DjogiContext was marked unsafe to continue after a nested atomic() future was dropped before the framework could run savepoint cleanup. Rust Drop cannot await ROLLBACK TO SAVEPOINT / RELEASE SAVEPOINT, so the safe contract is fail-closed: framework-owned operations reject further work, commit rolls the outer transaction back instead of committing it, and the caller must retry the outer unit of work from a fresh transaction. Classified as terminal by DjogiError::is_transient — retrying against the same poisoned context cannot make the transaction safe to commit.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§reason: &'static str

Static reason tag naming the poison source.

§

#[non_exhaustive]
SessionStatementDisallowedInTransaction

A transaction-backed raw SQL call attempted a session-scoped statement that atomic() cannot safely scrub on commit/rollback. This variant is used by the raw SQL bypass harness to reject session-level control statements such as plain SET, RESET, LISTEN, UNLISTEN, PREPARE, DEALLOCATE, and DISCARD when the context is already inside an atomic() transaction. Those statements either outlive the surrounding transaction entirely or invite callers to assume rollback will clean them up when Postgres semantics say otherwise. statement is the canonical top-level keyword ("SET", "RESET", etc.) that triggered the refusal. The fix is structural: use a transaction-local form such as SET LOCAL / SET CONSTRAINTS / SET TRANSACTION, or run the session-scoped statement on a pool-backed context outside the transaction. Classified as terminal by DjogiError::is_transient retrying the same closure against the same SQL will fail the same way.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§statement: &'static str

Canonical top-level statement keyword that triggered the refusal.

§

#[non_exhaustive]
RawTransactionControlDisallowedInTransaction

A transaction-backed raw SQL call attempted to issue transaction-control SQL through the raw escape hatch instead of using Djogi’s transaction lifecycle methods. This variant is used by the raw SQL bypass harness (#306) to reject transaction-control statements such as BEGIN, START TRANSACTION, COMMIT, ROLLBACK, END, ABORT, SAVEPOINT, RELEASE [SAVEPOINT], and ROLLBACK [WORK|TRANSACTION] TO [SAVEPOINT] when the context is already inside an atomic() transaction. Those statements bypass framework bookkeeping: raw COMMIT skips on_commit callback drain, raw ROLLBACK skips rollback cleanup and callback discard, and raw savepoint control desynchronizes savepoint_depth. statement is the canonical top-level transaction-control keyword ("BEGIN", "COMMIT", etc.) that triggered the refusal. The fix is structural: use Djogi’s atomic() / commit() / rollback() API, or run the transaction-control SQL on a pool-backed context outside any atomic() scope. Classified as terminal by DjogiError::is_transient retrying the same closure against the same SQL will fail the same way.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§statement: &'static str

Canonical top-level transaction-control statement that triggered refusal.

§

#[non_exhaustive]
UnsupportedAggregate

An aggregate’s DISTINCT modifier combination is not supported by Postgres syntax or by Djogi’s current IR.

§When this surfaces

Raised by the fetch-time legality check in [crate::expr::sql::check_aggregate_legality] for three value-aggregate cases that cannot be represented by the kind-state split alone:

  • COUNT(DISTINCT *)COUNT(DISTINCT *) is not valid SQL. Use COUNT(DISTINCT col) via crate::query::field::FieldRef::count instead.
  • STRING_AGG(DISTINCT col, sep) without per-aggregate ORDER BY Postgres requires an explicit ordering when DISTINCT is combined with STRING_AGG. Chain .order_by(...) on the aggregate to make the shape well-formed.
  • COUNT(*) ORDER BY ... — the COUNT(*) emitter has no argument slot to attach per-aggregate ordering to, so accepting the modifier would silently drop it. op is the aggregate function keyword (e.g. "COUNT(*)", "STRING_AGG"). reason is a human-readable description of why the combination is rejected.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§op: &'static str

The aggregate function keyword or name, e.g. "COUNT(*)" or "STRING_AGG".

§reason: &'static str

Human-readable explanation of why this combination is rejected.

§

#[non_exhaustive]
InvalidSubqueryModifier

A subquery conversion rejected a modifier or quantified operator that does not have valid SQL meaning in that subquery position.

§When this surfaces

  • VisageQuerySet::selecting and VisageExists::new reject order_by / limit / offset carried on a visage queryset: silently dropping those clauses would change semantics.
  • Quantified subquery comparisons reject IS [NOT] DISTINCT FROM, which has no Postgres ANY / ALL form.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§op: &'static str

The rejecting entry point or operator family.

§reason: &'static str

Human-readable explanation of the rejected modifier.

§

AliasCollision

The emitted SELECT list contains two columns with the same alias; the decoder would read the wrong value for one of the columns. This is a Djogi internal bug — a future API extension likely introduced a path that collides with a group-key column name or another aggregate alias. The check runs before any SQL is sent to Postgres so the collision is caught immediately rather than silently returning wrong data.

Fields

§alias: String

The alias string that appears more than once in the SELECT list.

§

#[non_exhaustive]
PoolTimeout

A pool checkout exceeded its configured wait / create / recycle timeout. Pairs with DjogiPoolBuilder::timeout so callers can branch on saturation explicitly without inspecting the underlying deadpool_postgres::PoolError. phase distinguishes the deadpool timeout type:

  • "wait" — the pool is at max_size and no slot freed within the configured wait window. Tune max_size upward or stop holding connections across awaits unrelated to the database.
  • "create"Manager::create (opening a fresh socket) timed out. Network or DB-side problem, not pool sizing.
  • "recycle" — recycling an existing object on the checkout path timed out. Same root cause as "create" for Verified/Clean recycling methods that issue queries. All three are saturation / slow-recovery signals: the right response is to back off and retry, not to fail the operation permanently. DjogiError::is_transient returns true for PoolTimeout so generic retry helpers that branch on is_transient (or its inverse is_terminal) treat pool timeouts as retryable rather than dead-lettering them as permanent business failures. Note that djogi exposes two retry helpers with different policy: crate::transaction::retry_on_conflict retries immediately, while crate::transaction::retry_on_conflict_with_backoff sleeps between transient failures using crate::transaction::TransactionRetryBackoff. Pool saturation usually belongs on the backoff path, not the immediate-retry path. Callers that need a bespoke policy can still match on PoolTimeout explicitly, and the backoff policy can include/exclude PoolTimeout retries via with_retryable_error_classes(...).

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§phase: &'static str

Which deadpool timeout fired — "wait", "create", or "recycle". A &'static str because the set of phases is closed and tracking the exact variant lets callers match on it in tracing without depending on deadpool’s enum.

§

SetRoleOutsideTransaction

DjogiContext::set_role was invoked on a pool-backed context rather than inside an atomic transaction. introduces this variant for the security-overlay row-level security helper: SET LOCAL ROLE is bound to the surrounding transaction and reverts at COMMIT/ROLLBACK, so calling it outside a transaction would either fail outright or — worse leak the role onto the pooled connection where the next checkout-victim would inherit it. Surfacing this as a dedicated variant lets callers branch on the misuse without inspecting the underlying SQLSTATE. Classified as terminal by DjogiError::is_transient retrying the same closure cannot turn a pool-backed context into a transactional one.

§

InvalidRoleName(String)

DjogiContext::set_role was invoked with a role name that fails the byte-level Postgres identifier check. introduces this variant so role-name validation surfaces before any SQL is sent — the framework refuses to interpolate an untrusted string into SET LOCAL ROLE even when the caller has already quoted it. The accepted grammar is the standard Postgres unquoted identifier shape: an ASCII letter or underscore followed by ASCII alphanumerics or underscores, up to 63 bytes. Embedded quotes, control characters, and non-ASCII bytes are all rejected. The variant carries the offending name so log lines and error reports can identify what was rejected. Classified as terminal by DjogiError::is_transient a malformed role name is a programming error, not a race-condition.

§

Predicate(PortablePredicateError)

A portable predicate could not be lowered to SQL. installs the direct-Q<T> SQL walker; portable predicate leaves dispatch through crate::model::Model::__djogi_emit_field_predicate (overridden by PR2d’s macro on every PK-backed #[model]-emitted impl). Failure modes — unknown model, unknown field, unknown LookupOp for a known field, payload-shape mismatch, future Sassi predicate variant — surface here as a typed [crate::query::PortablePredicateError] before the SQL ever touches the database. Classified as terminal by DjogiError::is_transient — a portable-predicate lowering failure is a framework / model invariant violation, not a transient database condition. Retrying the same closure cannot turn an unknown field into a known one.

§

#[non_exhaustive]
SetOpArmInvalid

A SetOpQuerySet arm carried state that cannot ride through a Postgres set-operation subquery: registered prefetch paths, registered select_related paths, a row-level lock, or a cache binding. Cluster 4B (issue #101) introduces this variant alongside the typed set-op surface (.union(...) / .union_all(...) / .intersect(...) / .except(...)).

§Why this is a typed error, not a silent drop

Quietly stripping select_related / prefetch registrations when an arm enters a set op would silently change the row shape the caller expected: select_related extends the projection, prefetch fans out follow-up queries on the returned rows. Both would either change the column count (breaking the set-op type compatibility rule) or silently drop data the caller asked for. Returning a typed error at the terminal — before any SQL hits the database — keeps the failure mode actionable. Locks (FOR UPDATE) inside a set-op subquery are rejected by Postgres at parse time anyway; we surface a higher-fidelity error before the round trip. side identifies which arm tripped the check ("left" or "right"); reason is a short human-readable explanation that names the offending registration. Classified as terminal by DjogiError::is_transient the caller built an incompatible set-op shape; retrying the same call cannot turn a .cache(...)-bound arm into a cache-free one.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§table: &'static str
§side: &'static str
§reason: &'static str
§

#[non_exhaustive]
SetOpOuterOrderingInvalid

A SetOpQuerySet’s outer ORDER BY carried an expression-form ordering term that Postgres rejects on set-operation outer ordering. (issue #101) introduces this variant alongside the typed set-op surface.

§Why this is a typed error, not a silent pass-through

Postgres set-operation ORDER BY only accepts output column names (or column position numbers) — arbitrary expressions are rejected at parse time. Today the only way to produce a non-column outer ordering is the spatial order_by_distance(...) helper, which emits a ST_Distance(...) expression. Letting that ride through to Postgres would surface a low-level parser error (syntax error at or near "(", ORDER BY position out of range, or similar) that does not name the offending operation. Djogi catches the case at SQL-build time and surfaces a higher-fidelity error before the round trip, naming the table and explaining the constraint. table identifies the model whose set-op carries the incompatible ordering; reason is a short human-readable explanation that names the kind of ordering rejected and the recommended workaround. Classified as terminal by DjogiError::is_transient the caller built an incompatible set-op shape; retrying the same call cannot turn an expression-form ordering into a column-form one. The fix is at the call site.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§table: &'static str
§reason: &'static str
§

IsolationLevelOnNestedScope

djogi::transaction::atomic_with(level, &mut tx_ctx, ...) was invoked on a transaction-backed crate::DjogiContext — i.e. inside an already-open atomic scope. (issue #168) introduces this variant alongside the typed crate::transaction::IsolationLevel surface. Postgres pins the isolation level for the entire transaction at the outer BEGIN; SAVEPOINT does not open a sub-transaction with its own isolation knob, and SET TRANSACTION ISOLATION LEVEL issued after the first non-control statement is rejected with SQLSTATE 25001 (active SQL transaction). Surfacing this as a typed variant lets callers branch on the misuse before the SQL flies; the alternative would be a deferred SQLSTATE surprise that names neither the outer BEGIN nor the requested level. The variant carries the crate::transaction::IsolationLevel the caller requested so log lines and error reports identify what was rejected. Use crate::transaction::atomic for nested scopes — the savepoint inherits the outermost transaction’s isolation level. Classified as terminal by DjogiError::is_transient — a nested-scope isolation request is a programming error, not a race condition. Retrying the same closure cannot turn a savepoint into a fresh outermost transaction.

Fields

§requested: IsolationLevel

Isolation level the caller requested. &'static-like the enum is Copy so logging callers can read it without borrowing the variant.

§

ConstraintModeOutsideTransaction

DjogiContext::defer_constraints / set_constraints_immediate was invoked on a pool-backed context rather than inside an atomic transaction. issue #169) introduces this variant alongside the typed crate::transaction::DeferScope surface. SET CONSTRAINTS is transaction-scoped in Postgres — outside a transaction it would either fail outright or, on the implicit per-statement transaction surrounding a single statement, evaporate before any subsequent statement could observe the deferred state. Both outcomes are programming errors, so the framework refuses to issue the SQL. Classified as terminal by DjogiError::is_transient retrying cannot turn a pool-backed context into a transactional one. Wrap the call in crate::transaction::atomic to get a transaction scope.

§

UnknownConstraintName(String)

DjogiContext::defer_constraints / set_constraints_immediate was called with a crate::transaction::DeferScope::Named payload that referenced an unknown constraint. issue #169) introduces this variant. “Unknown” means the constraint name was not found on any #[derive(Model)]-emitted crate::DeferrabilitySpec inventory entry. The lookup uses the conventional <table>_<column>_fkey shape ({table}_{column}_fkey, truncated to Postgres’ 63-byte identifier limit when necessary) for foreign-key constraints declared in adopter #[model] structs. Surfacing the typo as a typed error before the SQL flies is the value-add over ctx.raw_execute("SET CONSTRAINTS \"typo\" DEFERRED"): Postgres would raise 42704 (undefined_object) for an unknown constraint, but only after a round trip and without naming the descriptor it should have come from. The variant carries the offending name so log lines identify what was rejected. Classified as terminal by DjogiError::is_transient — retrying cannot turn an unknown name into a known one.

§

ConstraintNotDeferrable(String)

DjogiContext::defer_constraints was called with a crate::transaction::DeferScope::Named payload that referenced a constraint declared as non-deferrable (#[field(deferrable = false)], the default). Issue #169) introduces this variant. Postgres rejects SET CONSTRAINTS <name> DEFERRED on a non-deferrable constraint with SQLSTATE 0A000 (feature_not_supported). The framework checks the descriptor’s crate::DeferrabilitySpec inventory and surfaces a typed error before the SQL flies — same value-add as Self::UnknownConstraintName. The fix is at the model declaration: declare the FK as #[field(deferrable = true)] (and optionally initially_deferred = true for DEFERRABLE INITIALLY DEFERRED). The constraint must be deferrable to participate in SET CONSTRAINTS at runtime. Classified as terminal by DjogiError::is_transient — a non-deferrable constraint cannot be deferred at runtime regardless of how many retries.

§

EmptyDeferConstraintsScope

DjogiContext::defer_constraints / set_constraints_immediate was called with crate::transaction::DeferScope::Named carrying an empty slice. issue #169) follow-up fix. SET CONSTRAINTS <name list> DEFERRED|IMMEDIATE requires at least one name; Postgres rejects the bare-comma grammar with SQLSTATE 42601 (syntax error). Composing the SQL from an empty slice would produce SET CONSTRAINTS DEFERRED — an extra space + missing list. Reject before SQL composition so the caller gets a typed error naming the misuse rather than a deferred Postgres parse error. The canonical fix is one of:

  • drop the Named wrapper and use DeferScope::All if the intent is “every deferrable constraint”;
  • skip the call entirely when the names slice is empty;
  • pass at least one valid constraint name. Classified as terminal by DjogiError::is_transient retrying with the same empty slice cannot succeed.
§

ConflictingDeferrabilitySpec

Runtime inventory walk for [DjogiContext::defer_constraints] / [DjogiContext::set_constraints_immediate] observed two crate::DeferrabilitySpec entries sharing the same (model_type_name, field_name) key but disagreeing on (deferrable, initially_deferred). issue #169) — . inventory::iter order is not deterministic across builds. A silent last-writer-wins on a disagreeing duplicate would make the runtime validator non-deterministic — one build would accept a SET CONSTRAINTS <name> DEFERRED request, the next would reject it as ConstraintNotDeferrable. Mirror the projection-time [ConflictingDeferrabilitySpec] gate in migrate::projection so the framework fails closed at both schema-build time and transaction-control time. Idempotent duplicates (same key, identical values) are accepted — they can arise from inventory::submit! chains across crates re-exporting the same model and carry no semantic disagreement. Classified as terminal by DjogiError::is_transient the conflict is a build-time inventory misconfiguration, not a race condition. Fix is at the model declaration. [ConflictingDeferrabilitySpec]: crate::migrate::projection::ProjectionError::ConflictingDeferrabilitySpec

Fields

§model_type_name: String

Rust type name carrying the FK field.

§field_name: String

Field name (Postgres column name).

§first: (bool, bool)

(deferrable, initially_deferred) from the first spec the validator observed.

§second: (bool, bool)

(deferrable, initially_deferred) from the second spec the validator observed.

§

OrphanDeferrabilitySpec

Runtime inventory walk for [DjogiContext::defer_constraints] / [DjogiContext::set_constraints_immediate] observed a crate::DeferrabilitySpec whose model_type_name has no matching crate::ModelDescriptor entry. Cluster 4 (issue #169) — . The descriptor is the source of truth for type_name → table_name. A DeferrabilitySpec without a matching ModelDescriptor means the FK is not really registered, but would be silently skipped by the prior implementation. That silent skip is the bug: a valid-looking constraint name <expected_table>_<field>_fkey would then surface as UnknownConstraintName instead of the actual root cause (the missing descriptor). #[derive(Model)] emits the descriptor + the deferrability spec side by side, so an orphan spec only fires under pathological partial-emission conditions — typically a hand-written inventory::submit! outside the macro. Classified as terminal by DjogiError::is_transient the cause is a build-time inventory misconfiguration.

Fields

§model_type_name: String

Rust type name carrying the orphan FK field.

§field_name: String

Field name (Postgres column name).

§

DuplicateConstraintName

Runtime inventory walk for [DjogiContext::defer_constraints] / [DjogiContext::set_constraints_immediate] observed two distinct (model_type_name, field_name) pairs whose conventional FK constraint names collide. Cluster 4 (issue #169) — . The constraint-name convention is <table>_<column>_fkey (truncated to Postgres’ 63-byte identifier limit). Truncation can produce collisions for long table or column names — and a collision means the runtime validator has no way to know which FK the adopter meant. Fail closed. The fix at the model declaration is to shorten the offending table or column name, or to declare an explicit constraint name once that surface lands (out of scope for #169). Classified as terminal by DjogiError::is_transient the conflict is a build-time naming collision.

Fields

§constraint_name: String

The constraint name that two distinct fields produce.

§first_model: String

First model the validator observed under this name.

§first_field: String

First field the validator observed under this name.

§second_model: String

Second model the validator observed under this name.

§second_field: String

Second field the validator observed under this name.

§

ConcurrentReadsRequirePoolContext

QuerySet::merge_into was invoked on a transaction-backed context. (issue #173) introduces this variant alongside the typed concurrent-reads helper. A transaction owns one Postgres connection; cloning the context for concurrent reads would either hand out aliasing access to the same connection (Postgres protocol violation) or silently break the transaction boundary. Both are programming errors, so the framework refuses. The correct shape for concurrent reads is on a pool-backed context: each clone gets a fresh pool checkout, the two contexts operate on independent connections, and tokio::try_join! over typed reads composes without an E0499 mutable-borrow conflict. Classified as terminal by DjogiError::is_transient retrying cannot turn a transaction-backed context into a pool-backed one. Move the concurrent-reads block outside the surrounding atomic().

§

#[non_exhaustive]
MergeSourceInvalid

QuerySet::merge_into observed a source queryset with state that cannot be safely represented in a MERGE statement: prefetch, select_related, cache, lock, or distinct. Issue #178. Classified as terminal by DjogiError::is_transient.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§table: &'static str
§reason: &'static str
§

#[non_exhaustive]
MergeBranchInvalid

QuerySet::merge_into observed an invalid branch configuration: unreachable branches (same-kind unconditional branch follows another), duplicate target columns in an update or insert action, or manual updated_at assignment in an update action. Issue #178. Classified as terminal by DjogiError::is_transient.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§table: &'static str
§reason: String
§

#[non_exhaustive]
MergeNoBranches

QuerySet::merge_into was invoked without any ON conditions or without any WHEN branches. Issue #178. Classified as terminal by DjogiError::is_transient.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§table: &'static str
§reason: String
§

PresentationStartup(Vec<PresentationStartupError>)

One or more presentation codecs failed startup validation. Returned by validate_startup_inventory when any PresentationCodecUsage entry’s validate_startup hook returns an error. This variant is the conversion target for pool-construction callers (DjogiPool::connect, DjogiPool::from_database_config, DjogiPoolBuilder::build) that call validate_startup_inventory before accepting traffic. GH #227 wires those callers. The inner Vec carries one PresentationStartupError per failing codec usage. Each entry names the (model, field, scope, codec) quadruple and the underlying error so operators can identify every misconfigured codec in one pass rather than discovering failures one at a time. Classified as terminal by the framework — a codec with a missing or invalid key cannot serve traffic until the key is provided. The fix is an environment-variable or configuration change, not a retry. Display includes the total count plus a concise summary of each failing usage so operator logs can point directly at the actionable (model, field, scope, codec) entry without requiring Debug.

§

#[non_exhaustive]
UnsupportedPostgresVersion

Connected PostgreSQL server version is below Djogi’s minimum supported version. Raised by check_postgres_version preflight when the detected major version is less than 18. detected_major and detected_minor are the actual server version components. minimum_major is Djogi’s minimum supported major version (always 18).

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§detected_major: u32
§detected_minor: u32
§minimum_major: u32
§

#[non_exhaustive]
StalePhaseZeroStatement

A Phase 0 migration statement was classified as stale at the deepest execution boundary (immediately before raw batch_execute). This variant is the statement-level safety net in [migrate::runner::execute_runner_statement] — the runner’s carve-out for Phase 0 version allows raw batch_execute to bypass the session-statement guard, so this classifier catches stale artifacts that somehow evaded the pre-bootstrap artifact checks.

What triggers this. The statement-level guard emits seed-dml for top-level HeeRanjID seed-table mutations and generated-stale for literal database-default statements such as ALTER DATABASE "<hardcoded_name>" SET heer.node_id or heer.ranj_node_id instead of dynamic defaults like current_database(). Current production Phase 0 omits node seeding entirely; single-node-dev current uses dynamic EXECUTE format('ALTER DATABASE %I ...', current_database(), ...).

statement carries the offending SQL prefix so log lines can identify what was rejected. Classified as terminal — a stale statement against the same database cannot succeed on retry.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§refusal_reason: &'static str

Short refusal reason tag ("seed-dml" or "generated-stale").

§statement: String

Offending SQL statement (truncated for log safety).

Implementations§

Source§

impl DjogiError

Source

pub fn not_found(table: &'static str) -> Self

Construct a NotFound error with a table-name context. This is the public escape hatch for #[non_exhaustive] on the NotFound variant: struct-expression construction is blocked outside this crate, so #[model]-expanded CRUD methods (which run in user crates) call this constructor instead. Keep the signature stable any future additional context fields must gain their own constructor or builder rather than changing this one.

Source

pub fn multiple_objects(table: &'static str, count_seen: usize) -> Self

Construct a MultipleObjects error with a table name and the number of rows actually observed. Mirror of not_found — exists so that cross-crate callers (macro output, future filter-layer builders) can produce this variant without running into #[non_exhaustive].

Source

pub fn relation_unloaded(model: &'static str, field: &'static str) -> Self

Construct a RelationUnloaded error naming the model and relation field that the caller asked to resolve without loading. Exists for the same reason as not_found / multiple_objects: the #[non_exhaustive] attribute on the variant blocks struct-expression construction outside this crate, so macro-expanded code and + relation wrappers go through this constructor instead.

Source

pub fn missing_idempotency_key(model: &'static str) -> Self

Construct a MissingIdempotencyKey error naming the model whose #[model(idempotency_key = "...")] attribute was not declared. Mirror of not_found / multiple_objects — exists so that cross-crate callers (macro output in user crates) can produce this variant despite #[non_exhaustive] blocking struct- expression construction outside this crate.

Source

pub fn gone_aggregate( model: &'static str, id: String, reason: &'static str, ) -> Self

Construct a GoneAggregate error. Mirror of the other constructors — exists so that cross-crate callers can produce this #[non_exhaustive] variant. id is typically produced via format!("{}", pk) so the error is independent of the originating model’s Pk type.

Source

pub fn unsupported_postgres_version( detected_major: u32, detected_minor: u32, minimum_major: u32, ) -> Self

Construct an UnsupportedPostgresVersion error with the detected server version and the framework’s minimum supported major version. Mirror of the other constructors — exists so that cross-crate callers (the pg::preflight module, CLI entry points) can produce this variant despite #[non_exhaustive] blocking struct-expression construction outside this crate.

Source

pub fn invalid_subquery_modifier(op: &'static str, reason: &'static str) -> Self

Construct an InvalidSubqueryModifier error. The call sites for this variant all use literal strings, so the constructor keeps the shape &'static str rather than widening to an owned String.

Source

pub fn is_transient(&self) -> bool

Classify this error as transient (retrying the closure may succeed) or terminal (retrying will not help). retry_on_conflict uses this predicate to decide whether to re-run its closure. The contract:

VariantClassification
LockConflicttransient
Db with SQLSTATE 40001 / 40P01 / 55P03transient
Db with any other SQLSTATEterminal
NotFoundterminal
MultipleObjectsterminal
IdGenerationterminal
RelationUnloadedterminal
Decodeterminal
Serdeterminal
Validationterminal
MissingIdempotencyKeyterminal
GoneAggregateterminal
StreamOutsideTransactionterminal
TransactionPoisonedterminal
SessionStatementDisallowedInTransactionterminal
RawTransactionControlDisallowedInTransactionterminal
PoolTimeouttransient
SetRoleOutsideTransactionterminal
InvalidRoleNameterminal
IsolationLevelOnNestedScopeterminal
ConstraintModeOutsideTransactionterminal
UnknownConstraintNameterminal
ConstraintNotDeferrableterminal
EmptyDeferConstraintsScopeterminal
ConflictingDeferrabilitySpecterminal
OrphanDeferrabilitySpecterminal
DuplicateConstraintNameterminal
ConcurrentReadsRequirePoolContextterminal
UnsupportedPostgresVersionterminal
The Db row reflects the existing is_lock_error
classifier: Postgres SQLSTATEs 40001 (serialization
failure), 40P01 (deadlock detected), and 55P03
(lock not available / NOWAIT rejection) are the three
retryable codes. Unique-violation, foreign-key violation,
connection drops, and protocol errors all fall through to
terminal because retrying the same closure against a
constraint violation will fail the same way.
Source

pub fn is_terminal(&self) -> bool

Inverse of is_transient — returns true when retrying will not help. Provided as a convenience for call sites that read more naturally as err.is_terminal() than !err.is_transient(). Same contract, inverted.

Trait Implementations§

Source§

impl Debug for DjogiError

Source§

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

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

impl Display for DjogiError

Source§

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

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

impl Error for DjogiError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<AuthError> for DjogiError

Source§

fn from(source: AuthError) -> Self

Converts to this type from the input type.
Source§

impl From<DjogiError> for BackfillError

Source§

fn from(source: DjogiError) -> Self

Converts to this type from the input type.
Source§

impl From<DjogiError> for DaemonError

Source§

fn from(source: DjogiError) -> Self

Converts to this type from the input type.
Source§

impl From<DjogiError> for HookError

Source§

fn from(source: DjogiError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for DjogiError

Source§

fn from(source: Error) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for DjogiError

Bridge: convert tokio_postgres::Error into DjogiError.

Source§

fn from(e: Error) -> Self

Converts to this type from the input type.
Source§

impl From<Infallible> for DjogiError

InfallibleDjogiError coercion. Infallible has no inhabitants, so match never {} is exhaustive. The impl exists so macro-emitted chains that invoke <Visage as TryFrom<&Model>>::try_from(row)? propagate through ? uniformly regardless of whether the visage is scalar-only (the stdlib blanket returns Infallible) or relation-nesting (returns VisageError). Without this impl the scalar-only path fails compilation with “? couldn’t convert the error to DjogiError”.

Source§

fn from(never: Infallible) -> Self

Converts to this type from the input type.
Source§

impl From<VisageError> for DjogiError

Source§

fn from(source: VisageError) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

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<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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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<V> IntoPortableFieldValue<Option<V>> for V

Source§

fn into_portable_field_value(self) -> Option<V>

Convert self into the field’s declared portable value type. The returned value flows into Sassi’s Field<M, FieldValue>::eq / .gt / .in_ / etc. as the right-hand-side operand. Implementors must produce a value whose PartialEq / PartialOrd / Hash behaviour matches the on-disk column ordering — otherwise Punnu and the database row will disagree at evaluation time.
Source§

impl<V> IntoPortableFieldValue<Tracked<V>> for V

Source§

fn into_portable_field_value(self) -> Tracked<V>

Convert self into the field’s declared portable value type. The returned value flows into Sassi’s Field<M, FieldValue>::eq / .gt / .in_ / etc. as the right-hand-side operand. Implementors must produce a value whose PartialEq / PartialOrd / Hash behaviour matches the on-disk column ordering — otherwise Punnu and the database row will disagree at evaluation time.
Source§

impl<V> IntoPortableFieldValue<V> for V

Source§

fn into_portable_field_value(self) -> V

Convert self into the field’s declared portable value type. The returned value flows into Sassi’s Field<M, FieldValue>::eq / .gt / .in_ / etc. as the right-hand-side operand. Implementors must produce a value whose PartialEq / PartialOrd / Hash behaviour matches the on-disk column ordering — otherwise Punnu and the database row will disagree at evaluation time.
Source§

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

Source§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
Source§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
Source§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
Source§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
Source§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
Source§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
Source§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
Source§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
Source§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
Source§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
Source§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
Source§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
Source§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
Source§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
Source§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
Source§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
Source§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
Source§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
Source§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
Source§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
Source§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
Source§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
Source§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
Source§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
Source§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
Source§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
Source§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
Source§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
Source§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
Source§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
Source§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
Source§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
Source§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
Source§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
Source§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
Source§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
Source§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
Source§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
Source§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
Source§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
Source§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling Attribute value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
Source§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
Source§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
Source§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
Source§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
Source§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
Source§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
Source§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
Source§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi Quirk value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
Source§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
Source§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
Source§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
Source§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
Source§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
Source§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
Source§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
Source§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the Condition value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
Source§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new Painted with a default Style. Read more
Source§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more