Skip to main content

AppError

Enum AppError 

Source
#[non_exhaustive]
pub enum AppError {
Show 26 variants Validation(String), BinaryNotFound { name: String, }, RateLimited { detail: String, }, Timeout { operation: String, duration_secs: u64, }, Duplicate(String), Conflict(String), NotFound(String), MemoryNotFound { name: String, namespace: String, }, MemoryNotFoundById { id: i64, }, NamespaceError(String), LimitExceeded(String), Database(Error), Embedding(String), VecExtension(String), DbBusy(String), BatchPartialFailure { total: usize, failed: usize, }, Io(Error), Internal(Error), Json(Error), LockBusy(String), AllSlotsFull { max: usize, waited_secs: u64, }, JobSingletonLocked { job_type: String, namespace: String, }, EmbeddingSingletonLocked { namespace: String, }, LowMemory { available_mb: u64, required_mb: u64, }, Shutdown { signal: String, }, PreFlightFailed { source: Box<PreFlightError>, },
}
Expand description

Unified error type for all CLI and library operations.

Each variant corresponds to a distinct failure category. The AppError::exit_code method converts a variant into a stable numeric code so that shell callers and LLM agents can route on it.

§SemVer Policy

This enum is #[non_exhaustive]. New variants may be added in minor releases without breaking downstream match arms (use a wildcard _).

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

Validation(String)

Input failed schema, length or format validation. Maps to exit code 1.

This variant groups multiple validation failure causes. Callers that need programmatic retry decisions should use AppError::is_retryable instead of parsing the message string.

§

BinaryNotFound

External binary required for operation was not found in PATH. Maps to exit code 1.

Fields

§name: String
§

RateLimited

Remote service signaled rate limiting; caller should retry with backoff. Maps to exit code 1.

Fields

§detail: String
§

Timeout

Operation exceeded its time budget. Maps to exit code 1.

Fields

§operation: String
§duration_secs: u64
§

Duplicate(String)

A memory or entity with the same (namespace, name) already exists. Maps to exit code 9.

§

Conflict(String)

Optimistic update lost the race because updated_at changed. Maps to exit code 3.

§

NotFound(String)

The requested record does not exist or was soft-deleted. Maps to exit code 4.

§

MemoryNotFound

Memory lookup by (namespace, name) returned no row. Maps to exit code 4.

G55 S2 (v1.0.80): structural variant that carries the requested identifier and namespace, eliminating the “not found: unknown in namespace ‘X’” class of bugs that masked which lookup target failed. The display format matches the legacy string-based NotFound so the i18n replace-chain and external scripts that pattern-match on memory not found: name='N' in namespace 'NS' keep working.

Fields

§name: String
§namespace: String
§

MemoryNotFoundById

Memory lookup by integer id returned no row. Maps to exit code 4.

Fields

§id: i64
§

NamespaceError(String)

Namespace could not be resolved from flag, environment or markers. Maps to exit code 5.

§

LimitExceeded(String)

Payload exceeded one of the configured body, name or batch limits. Maps to exit code 6.

§

Database(Error)

Low-level SQLite error propagated from rusqlite. Maps to exit code 10.

§

Embedding(String)

Embedding generation via fastembed failed or produced the wrong shape. Maps to exit code 11.

§

VecExtension(String)

The sqlite-vec extension could not load or register its virtual table. Maps to exit code 12.

§

DbBusy(String)

SQLite returned SQLITE_BUSY after exhausting retries. Maps to exit code 15 (was 13 before v2.0.0; relocated to free 13 for BatchPartialFailure per PRD).

§

BatchPartialFailure

Batch operation failed partially — N of M items failed. Maps to exit code 13 (PRD 1822).

Reserved for use in import, reindex and batch stdin (BLOCK 3/4). Variant present since v2.0.0 even if call-sites do not yet exist — stable exit code mapping.

Fields

§total: usize
§failed: usize
§

Io(Error)

Filesystem I/O error while reading or writing the database or cache. Maps to exit code 14.

§

Internal(Error)

Unexpected internal error surfaced through anyhow. Maps to exit code 20.

§

Json(Error)

JSON serialization or deserialization failure. Maps to exit code 20.

§

LockBusy(String)

Another instance is already running and holds the advisory lock. Maps to exit code 75.

Use --allow-parallel to skip the lock or --wait-lock SECONDS to retry.

§

AllSlotsFull

All concurrency slots are occupied after the wait timeout. Maps to exit code 75.

Occurs when crate::constants::MAX_CONCURRENT_CLI_INSTANCES instances are already active and the wait limit crate::constants::CLI_LOCK_DEFAULT_WAIT_SECS is exhausted.

Fields

§max: usize
§waited_secs: u64
§

JobSingletonLocked

A heavy long-running job is already running for this job_type/namespace pair. Maps to exit code 75 (the same EX_TEMPFAIL code used by the CLI semaphore).

G28-B (v1.0.68): ensures at most one enrich, ingest --mode claude-code, or ingest --mode codex runs at a time per namespace. Use --wait-job-singleton <SECONDS> (per-command) to poll until the other invocation finishes.

Fields

§job_type: String
§namespace: String
§

EmbeddingSingletonLocked

G45: an LLM embedding operation is already running against the same (namespace, db) pair in another process. Exit code 75 (retryable). The caller can pass --wait-embed-singleton <SECONDS> to poll until the lock drops.

Fields

§namespace: String
§

LowMemory

Available memory is below the minimum required to load the model. Maps to exit code 77.

Returned when sysinfo reports available memory below crate::constants::MIN_AVAILABLE_MEMORY_MB MiB before starting the ONNX model load.

Fields

§available_mb: u64
§required_mb: u64
§

Shutdown

v1.0.82 (GAP-002 final): shutdown was requested via SIGINT, SIGTERM or SIGHUP before the current command completed. Maps to exit code crate::constants::SHUTDOWN_EXIT_CODE (19).

The signal name is preserved in the signal field so the JSON envelope emitted before exit can route the operator to a deterministic branch. Distinct from the legacy 128 + signal Unix convention (130/143/129) so LLM agents can match on a single code for “cancelled by user”.

Fields

§signal: String
§

PreFlightFailed

v1.0.87 (GAP-META-005, ADR-0045): pre-flight validation gate rejected the spawn before fork. Maps to exit code 16.

The source field carries the structured PreFlightError variant so callers and operators can route on the specific failure class (BinaryNotFound, ArgvExceedsArgMax, McpConfigInlineJsonRejected, McpConfigPathMissing, McpConfigPathInvalidJson, WalkUpMcpJsonInvalid, OutputBufferTooSmall, ClaudeConfigDirNotEmpty) instead of parsing the legacy detail: String representation.

This variant is permanent — retrying the same argv will fail identically. Operators must fix the underlying condition (install the binary, shorten the body, override CLAUDE_CONFIG_DIR, substitute the inline --mcp-config '{}' for a tempfile path, etc.) before retrying.

Fields

Implementations§

Source§

impl AppError

Source

pub fn exit_code(&self) -> i32

Returns the deterministic process exit code for this error variant.

The codes follow the contract documented in the README: 1 for validation, 9 for duplicates (moved from 2 in v1.0.52), 3 for conflicts, 4 for missing records, 5 for namespace errors, 6 for limit violations, 1014 for infrastructure failures, 13 for BatchPartialFailure (PRD 1822), 15 for DbBusy (migrated from 13 in v2.0.0), 20 for internal errors, 75 (EX_TEMPFAIL) when the advisory CLI lock is held or all concurrency slots are exhausted, and 77 when available memory is insufficient to load the embedding model.

§Examples
use sqlite_graphrag::errors::AppError;

assert_eq!(AppError::Validation("invalid field".into()).exit_code(), 1);
assert_eq!(AppError::Duplicate("ns/mem".into()).exit_code(), 9);
assert_eq!(AppError::Conflict("ts changed".into()).exit_code(), 3);
assert_eq!(AppError::NotFound("id 42".into()).exit_code(), 4);
assert_eq!(AppError::NamespaceError("no marker".into()).exit_code(), 5);
assert_eq!(AppError::LimitExceeded("body too large".into()).exit_code(), 6);
assert_eq!(AppError::Embedding("wrong dim".into()).exit_code(), 11);
assert_eq!(AppError::DbBusy("retries exhausted".into()).exit_code(), 15);
assert_eq!(AppError::LockBusy("another instance".into()).exit_code(), 75);
Source

pub fn is_retryable(&self) -> bool

Returns true when the error is transient and the operation may succeed on retry with backoff.

§Examples
use sqlite_graphrag::errors::AppError;

assert!(AppError::DbBusy("busy".into()).is_retryable());
assert!(AppError::LockBusy("held".into()).is_retryable());
assert!(!AppError::NotFound("x".into()).is_retryable());
assert!(!AppError::Validation("bad".into()).is_retryable());
Source

pub fn is_shutdown(&self) -> bool

Returns true when shutdown was requested by the user via signal.

Distinct from is_permanent because shutdown is a USER intent, not a state to retry against. The operation should be retried with --resume (GAP-001) when the persisted staging row still exists.

§Examples
use sqlite_graphrag::errors::AppError;

assert!(AppError::Shutdown { signal: "SIGINT".into() }.is_shutdown());
assert!(!AppError::Validation("x".into()).is_shutdown());
Source

pub fn is_permanent(&self) -> bool

Returns true when the error is permanent and must NOT be retried.

Complement to Self::is_retryable. Errors not classified by either method (e.g. Database, Io, Internal) are ambiguous — the caller decides based on context.

§Examples
use sqlite_graphrag::errors::AppError;

assert!(AppError::Validation("bad".into()).is_permanent());
assert!(!AppError::DbBusy("busy".into()).is_permanent());
Source

pub fn localized_message(&self) -> String

Returns the localized error message in the active language (--lang / SQLITE_GRAPHRAG_LANG).

In English the text is identical to the Display generated by thiserror. In Portuguese the prefixes and messages are translated to PT-BR.

Source

pub fn localized_message_for(&self, lang: Language) -> String

Returns the localized message for the explicitly provided language. Useful in tests that cannot depend on the global OnceLock.

§Examples
use sqlite_graphrag::errors::AppError;
use sqlite_graphrag::i18n::Language;

let err = AppError::NotFound("mem-xyz".into());

let en = err.localized_message_for(Language::English);
assert!(en.contains("not found"));

let pt = err.localized_message_for(Language::Portuguese);
assert!(pt.contains("n\u{e3}o encontrado"));

Trait Implementations§

Source§

impl Debug for AppError

Source§

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

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

impl Display for AppError

Source§

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

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

impl Error for AppError

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<Error> for AppError

Source§

fn from(source: Error) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for AppError

Source§

fn from(source: Error) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for AppError

Source§

fn from(source: Error) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for AppError

Source§

fn from(source: Error) -> Self

Converts to this type from the input type.
Source§

impl From<PreFlightError> for AppError

Bridges the structured PreFlightError produced by the pre-flight validation gate (v1.0.87, ADR-0045) into the unified AppError envelope. Lets spawners use the ? operator instead of hand-rolling AppError::PreFlightFailed { source: ... } at every call site, and keeps the variant alive as the canonical exit code 16 path rather than the dead code it was at v1.0.87.

Source§

fn from(source: PreFlightError) -> 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> ErasedDestructor for T
where T: 'static,

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