Skip to main content

ApiError

Enum ApiError 

Source
pub enum ApiError {
    Unauthorized,
    NotFound {
        code: &'static str,
        message: String,
    },
    BadRequest {
        code: &'static str,
        message: String,
    },
    TooManyRequests {
        code: &'static str,
        message: String,
    },
    Timeout {
        message: String,
    },
    Internal(String),
}
Expand description

Every failure the API can report, with the JSON body clients receive.

§Deviation from the design

Phase 2 design §7 specified a nested body carrying the status twice ({"error": {"code", "message", "status"}}). The body here is flat — {"error": "<code>", "message": "<text>"} — and the status is only in the HTTP status line. Rationale: the status is already authoritative on the wire and repeating it in the body is a second source of truth that can disagree with the status line. Flattening also means an agent parses one object with no branch before it can read the machine code.

error is a stable machine code drawn from a closed set (ApiError::code) and is what a client should branch on. The codes are the ones §7 enumerates; message is prose for humans and is not guaranteed to be stable across releases.

§Why NotFound and BadRequest carry their own code

Both map to a single HTTP status, so the status alone cannot tell an agent what went wrong: 404 covers both “no such index” and “no such node”, and 400 covers a missing param, an unparseable param, and a bad body. The status says what kind of failure; the code says which, which is what lets a client retry sensibly without matching on prose.

Variants§

§

Unauthorized

No Authorization header, wrong scheme, unknown key, or wrong secret.

§

NotFound

The request was well-formed but names something that does not exist.

Fields

§code: &'static str

Stable machine code, e.g. unknown_index.

§message: String

Human-readable detail.

§

BadRequest

The request itself is malformed (missing field, bad value).

Fields

§code: &'static str

Stable machine code, e.g. missing_param.

§message: String

Human-readable detail.

§

TooManyRequests

The request was authenticated and well-formed, but a limit of the caller’s plan refused it (paid-path S3). A distinct status — not a 400 with a quota-flavoured code — because 429 is the one answer a client can act on without parsing prose: stop, wait for the window the message names, retry then.

Fields

§code: &'static str

Stable machine code, e.g. index_quota_exceeded.

§message: String

Human-readable detail.

§

Timeout

A query outlived its plan’s per-request time limit.

Fields

§message: String

Human-readable detail. One timeout shape exists, so the code (request_timeout) is fixed rather than carried.

§

Internal(String)

Storage, indexing, or an unexpected internal failure.

Implementations§

Source§

impl ApiError

Source

pub const INTERNAL_CLIENT_MESSAGE: &'static str = "internal error"

The only message a client ever sees for an internal failure.

The Internal variant’s payload is operator detail — host filesystem paths, rusqlite error text, store file names — that helps the person running the server and must never reach a client (fleet release gate F-1). ApiError::body logs the payload server-side and renders this generic text instead.

Source

pub fn unknown_index(id: &str) -> Self

404 unknown_index: {id} does not name a database in the data dir.

Source

pub fn unknown_node(id: &str) -> Self

404 unknown_node: the index loaded, but the node is not in the graph.

Source

pub fn no_path(from: &str, to: &str) -> Self

404 no_path: no typed path connects the two nodes.

Not in the §7 table, which does not cover a well-formed path query whose answer is “these two symbols are unrelated”. The CLI rejects the same case rather than returning an empty path, so 404 is preserved and given its own code instead of being folded into unknown_index or reported as an empty 200.

Source

pub fn missing_param(name: &str) -> Self

400 missing_param: a required query parameter is absent or empty.

Source

pub fn invalid_param(name: &str, reason: &str) -> Self

400 invalid_param: a query parameter is present but unusable.

Source

pub fn invalid_body(reason: &str) -> Self

400 invalid_body: the request body is not the expected JSON shape.

Source

pub fn invalid_repo_path(reason: &str) -> Self

400 invalid_repo_path: repo_path is missing or is not a directory.

Source

pub fn invalid_repo_url(reason: &str) -> Self

400 invalid_repo_url: repo_url is unparseable, not a public HTTPS URL, or its clone failed (paid-path S2). The sibling of invalid_repo_path for the hosted ingest mode: one code per ingest field, so a client can branch on which source was refused without matching on prose.

Source

pub fn index_quota(plan: &str, limit: usize, current: usize) -> Self

429 index_quota_exceeded: the key already holds its plan’s active-index limit. Names the limit and the current count, so the caller knows exactly what must be deleted or expire before another creation can succeed.

Source

pub fn query_quota(plan: &str, limit: u64, used: u64, month: &str) -> Self

429 query_quota_exceeded: the key has used its plan’s monthly query allowance. The month is the UTC calendar month (see crate::limits); naming it tells the caller when the quota resets without a second request to ask.

Source

pub fn file_quota(plan: &str, limit: usize) -> Self

429 file_quota_exceeded: the tree holds more files than the plan’s per-index cap. The count is a lower bound (the walk stops just past the limit), so the message says “more than”.

Source

pub fn index_concurrency(plan: &str, limit: usize) -> Self

429 index_concurrency_exceeded: the key already runs its plan’s allowance of concurrent index operations.

Source

pub fn request_timeout(plan: &str, secs: u64) -> Self

504 request_timeout: the query did not finish within the plan’s per-request limit.

Source

pub fn internal(reason: impl Into<String>) -> Self

500 from any internal failure, carrying reason.

Source

pub fn code(&self) -> &'static str

The stable machine code clients branch on.

Source

pub fn body(&self) -> Value

Body as a JSON value; exposed for tests and for asserting shape.

This is the single render point for client responses (IntoResponse goes through it), so the Internal redaction lives here rather than at the variant’s many construction sites: the detail is written to the server’s stderr and the client receives ApiError::INTERNAL_CLIENT_MESSAGE. Every other variant’s message is prose about the caller’s own request and renders as before.

Trait Implementations§

Source§

impl Debug for ApiError

Source§

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

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

impl Display for ApiError

Source§

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

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

impl Error for ApiError

1.30.0 · 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 IntoResponse for ApiError

Source§

fn into_response(self) -> Response

Create a response.

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

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