Skip to main content

LowerError

Enum LowerError 

Source
pub enum LowerError {
    FeatureUnavailable {
        feature: Feature,
        negotiated: ProtocolVersion,
    },
    NoRuleForFeature {
        feature: Feature,
    },
    FieldNotRepresentable {
        field: String,
        expected: &'static str,
        detail: String,
        target: ProtocolVersion,
    },
}
Expand description

Why a value could not be expressed at the target revision.

Variants§

§

FeatureUnavailable

The value needs a feature the negotiated revision cannot express, and no policy authorises a downgrade.

Fields

§feature: Feature

The feature the value needs.

§negotiated: ProtocolVersion

The revision it could not be expressed at.

§

NoRuleForFeature

The policy names a feature it can degrade, but names no rule for it.

Distinct from LowerError::FeatureUnavailable because the fix is different: the caller asked for a downgrade and did not say how. Failing here rather than picking a rule is what keeps a policy from quietly choosing the destructive option.

Fields

§feature: Feature

The feature with no rule.

§

FieldNotRepresentable

A field the target revision types as a struct does not fit it.

This is the 2026-07-28 meta case, and it is deliberately not a LowerError::FeatureUnavailable. That variant says a revision cannot express a shape at all, so the fix is to negotiate something else or authorise a downgrade. This one says a value does not fit a shape: the same value lowers cleanly at 2025-06-18, where meta is an untyped serde_json::Value, and fails at every revision that types it. Reporting it as a missing feature would put a false claim in the error — that the field is unavailable at the older revision — and would refuse messages that lower perfectly well.

§Why no DegradeRule applies

Every other variant here can be talked out of by a policy, and three options were considered for this one. All three are worse than refusing:

  • Synthesise the missing member. A fabricated version reads as authoritative and was never sent by anyone.
  • Drop the field, keep the rest of meta. Silent data loss, and meta is exactly where a sender puts something it meant to be understood.
  • Move the value into the struct’s extra bag. This one is a trap. ResultMetaObject really does carry #[serde(flatten)] extra, so putting io.modelcontextprotocol/serverInfo in there serialises straight back out and looks lossless. It is not: the reader treats that key as a known member and tries to parse it as an Implementation, which is the parse that just failed here. So the document is unreadable by its intended reader, and building it anyway launders the rejection out of this layer and onto the peer — where the bridge looks healthy and the error lands a long way from its cause.

Refusing is the only option that leaves the failure where it can be diagnosed. Note this leaves nothing for a DegradePolicy to do, and that is the intent rather than an omission: the only rule available would discard the sender’s data.

§The blast radius is narrower than it looks

The IR holds meta as a raw value, so a meta lifted from a 2026-07-28 peer has already been through that peer’s deserialiser and will always re-parse. Only a value from a revision that treats meta as untyped, or one built by hand, can reach this.

Fields

§field: String

The JSON key that could not be represented.

§expected: &'static str

The type the target revision requires there.

§detail: String

Why the value did not fit it.

§target: ProtocolVersion

The revision that types the field.

Trait Implementations§

Source§

impl Clone for LowerError

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 LowerError

Source§

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

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

impl Display for LowerError

Source§

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

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

impl Eq for LowerError

Source§

impl Error for LowerError

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<LowerError> for BridgeError

Source§

fn from(source: LowerError) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for LowerError

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 LowerError

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