Skip to main content

DispatchError

Enum DispatchError 

Source
pub enum DispatchError {
Show 15 variants UnknownTool, NotCallable, UnknownMethod, UnknownResource, UnknownPrompt, HandlerFailed(String), MalformedParams, MalformedInitialize, UnnegotiableVersion, MalformedRequestMeta, UnsupportedVersion { requested: String, supported: Vec<String>, }, DuplicateInFlight(String), MissingClientCapability { required: Vec<&'static str>, }, TamperedRequestState, IdempotencyUnavailable(String),
}
Expand description

Why a tool call did not run.

Variants§

§

UnknownTool

No tool of that name is registered.

Deliberately the same answer for a tool that exists but is hidden from this session: the difference would let a client probe for the existence of a tool it may not see. The server still logs which it was.

§

NotCallable

The tool is registered, but the session did not negotiate the features it requires.

§

UnknownMethod

No method of that name exists.

Refused on the method, not on a tool, because the caller named a method and there is no tool to say anything about.

§

UnknownResource

No resource of that URI is registered, or it is listed without a reader.

Two causes share one answer because a peer cannot tell them apart: a listing is a promise, so a resource that appears in resources/list and then refuses to be read is the same failure as one that was never there, and naming which of the two happened tells the peer nothing it can act on.

§

UnknownPrompt

No prompt of that name is registered, or it is listed without a getter.

§

HandlerFailed(String)

A registered reader or getter refused, naming why.

Carries the handler’s own message rather than a category, because the peer is a client and the only thing it can do with a category is show it to a user who would rather read what went wrong.

§

MalformedParams

tools/call params were not the shape a call has to be: not an object, no string name, or an arguments that is not an object.

A distinct variant from UnknownTool because a call with no name at all has not failed to find a tool — it never named one, and answering “no such tool” would send the caller looking for a tool that works.

§

MalformedInitialize

initialize params were not the shape the handshake has to be.

Separate from MalformedParams because the two failures are not the same event: that one says a tool call named nothing, and this one says the one request that establishes a session arrived in a shape that would have to be guessed at. A peer sending it has a bug worth naming, not a tool to go looking for.

Covers a body that is not an object, a missing or non-string protocolVersion, a string that is not a protocol version, a missing or non-object capabilities, and a clientInfo with no name.

§

UnnegotiableVersion

The session is on a revision this build has no wire types for.

Distinct from a refused method (UnknownMethod) because nothing about the request was wrong: the method exists, the params parse, and the answer cannot be built because the revision the session settled on is one negotiate_server would have to counter- offer. The session should never be in this state — it is reported rather than papered over, because the alternative is emitting a result whose shape the revision cannot express.

§

MalformedRequestMeta

A SEP-2575 request arrived without the _meta the schema requires.

2026-07-28 makes RequestParams._meta required on every request and requires two keys in it — the revision and the client’s capabilities — because there is no handshake to carry them and no session to remember them on. A request missing either is a well-formed message with a missing argument, which is -32602 and not a transport refusal.

Its own variant rather than a reuse of MalformedInitialize because the two are different failures with different fixes: one says the handshake arrived in a shape that would have to be guessed at, this says the shape is right and a required key is not there.

§

UnsupportedVersion

A SEP-2575 request named a revision this build does not implement.

Not MalformedParams, and the difference is the whole point of the code the specification assigns: -32022 with data.supported is what lets a client retry against a version this server does speak, where -32602 would send it looking for a bug in its own request.

Fields

§requested: String

The revision the client asked for, as it wrote it.

§supported: Vec<String>

Every revision this build speaks, for the client to choose from.

§

DuplicateInFlight(String)

A second request arrived with an id this session is still working on.

The JSON-RPC reading, and the reason it is an error rather than a queue: the first request is a real, running, side-effecting call, and the second carries no way to say what should happen to it. Running the tool twice is the answer a retry gets by accident, and this is the answer it gets on purpose. A client that wants the first result waits for it and retries later — at which point the id is Completed and comes straight back.

§

MissingClientCapability

Serving the request needs client capabilities the request did not declare (SEP-2575, -32021).

Raised when a handler answers with an InputRequiredResult asking for something the client said it cannot do: sending it anyway would ask a client to sample or elicit after it declined to, and the specification is explicit that a server “MUST NOT rely on capabilities the client has not declared”.

Fields

§required: Vec<&'static str>

The capability names, as ClientCapabilities keys.

§

TamperedRequestState

A SEP-2322 requestState did not verify.

-32602, because the state is a request parameter and this one is not a value this server issued. Refused before the handler runs, so no handler can be made to act on a state a client wrote.

§

IdempotencyUnavailable(String)

The store holding recorded results could not be reached.

Reported rather than swallowed because the alternative is the one thing this whole path exists to prevent: a store that errors, a caller that treats the error as “no claim”, and a tool that runs a second time. Failing the call is the only answer that does not charge a client twice behind its back.

Implementations§

Source§

impl DispatchError

Source

pub const fn jsonrpc_code(&self) -> IrErrorCode

The JSON-RPC code this refusal is reported as.

Lives here rather than in a transport adapter because it is a property of the error, not of the way it is written down. It sat in the stdio adapter until the HTTP router needed the same mapping, and the two options at that point were both wrong: copy it and let the copies drift apart, or reach into another adapter and break the layering.

Every refusal gets an answer. The alternative is to drop it, which leaves the peer waiting on a response that is never coming — and a server that hangs is worse than one that says no. The codes are the closest the standard offers: a method nobody serves is -32601, a call that does not name something callable is -32602, and a session that did not negotiate a feature — or one settled on a revision this build cannot serve — is a server-side condition rather than either.

A malformed initialize is -32602 like any other malformed params: the peer sent a request whose body it could not have meant, which is the same condition whatever the method was.

§Examples
assert_eq!(
    DispatchError::UnknownMethod.jsonrpc_code(),
    IrErrorCode::MethodNotFound,
);
assert_eq!(
    DispatchError::MalformedParams.jsonrpc_code(),
    IrErrorCode::InvalidParams,
);
Source

pub fn wire_data(&self) -> Option<JsonObject>

The data member this refusal’s code requires, if it has one.

-32022 carries the revision the client asked for and every revision this build speaks; -32021 carries requiredCapabilities as a ClientCapabilities object keyed by what is missing — not an array of names, because the schema types it as the object a client declares. Every other refusal carries none. One definition, so stdio and HTTP cannot disagree about it.

Source

pub fn as_wire(&self) -> (IrErrorCode, String)

The code and message pair a transport writes to the wire.

The message is thiserror’s own for the variant, never the method name the peer chose: a method name is a JSON string a peer controls, and JSON permits a newline inside one, so echoing it into a log line would let a peer close that line and open one of its own.

Trait Implementations§

Source§

impl Clone for DispatchError

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DispatchError

Source§

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

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

impl Display for DispatchError

Source§

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

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

impl Eq for DispatchError

Source§

impl Error for DispatchError

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 From<IdempotencyError> for DispatchError

Source§

fn from(error: IdempotencyError) -> Self

Keeps a poisoned or absent store from reading as an absent claim.

Source§

impl From<OutcomeError> for DispatchError

Source§

fn from(error: OutcomeError) -> Self

A reader or getter that could not produce a document failed.

Every variant becomes DispatchError::HandlerFailed carrying the outcome’s own message. None of them is a bad request — the peer named a resource or a prompt that exists and sent well-formed params — so reporting any of them as InvalidParams would send a client looking in its own request for something it got right.

Source§

impl PartialEq for DispatchError

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for DispatchError

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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 = !

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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

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