pub enum RouterBuildError {
Show 14 variants
InvalidSessionBackend(SessionBackendConfigError),
InvalidIdempotencyBackend(String),
InvalidSubmitTokenBackend(String),
FrameworkRouteOverlap {
path: String,
existing: &'static str,
incoming: &'static str,
},
InvalidOpenApiPath {
field: &'static str,
value: String,
},
DuplicateOpenApiPath {
path: String,
},
OpenApiPathCollision {
field: &'static str,
path: String,
},
UnregisteredApiVersion {
route_name: String,
version: String,
},
InvalidMcpPath {
value: String,
},
McpPathCollision {
path: String,
method: String,
},
DuplicateUserRoute {
method: String,
path: String,
existing: String,
incoming: String,
},
DuplicateNestPrefix {
prefix: String,
owners: String,
},
ConflictingRouteShape {
existing: String,
existing_path: String,
incoming: String,
incoming_path: String,
},
LocalePrefixPathCollision {
locale: String,
path: String,
generated: String,
},
}Expand description
The refusal AppBuilder::plugin_route_infos
and route_listing::collect_route_infos return.
Re-exported from the crate-private router module because both of those
are public functions that hand it back: without this, a caller could not
name the type, match its variants, or write the signature of a function
that forwards it.
Errors that can occur during the router build process.
These errors are typically fatal and represent configuration or routing definition issues that must be fixed before the application can start.
Variants§
InvalidSessionBackend(SessionBackendConfigError)
The session backend configuration is invalid (e.g. Redis without a URL).
InvalidIdempotencyBackend(String)
The idempotency backend configuration is invalid.
InvalidSubmitTokenBackend(String)
The submit-token backend configuration is invalid for production — an
explicit [security.submit_token].backend = "memory" cannot safely
deduplicate submits across replicas. Mirrors the idempotency
production-memory fail-fast.
FrameworkRouteOverlap
A user-defined route conflicts with a framework-provided route.
Fields
InvalidOpenApiPath
An OpenApiConfig path (e.g. openapi_json_path or
swagger_ui_path) is not a valid route path (must start with /
and be non-empty).
Fields
DuplicateOpenApiPath
openapi_json_path and swagger_ui_path collide on the same
URL. Mounting both would cause axum to panic on overlapping
method routes at startup.
OpenApiPathCollision
An OpenAPI mount path overlaps with an existing GET handler,
which would panic at axum::Router::merge time.
Fields
UnregisteredApiVersion
A route is annotated with an API version that is not registered.
InvalidMcpPath
The MCP mount path (from AppBuilder::mount_mcp)
is not a valid route path. axum requires paths to start with /, so an
invalid path is surfaced here rather than panicking at mount time.
McpPathCollision
The MCP mount path collides with an existing application route at the
same path. Mounting the MCP endpoint there would panic at
axum::Router::merge time on overlapping method routes, so this is
surfaced as a recoverable error instead.
Fields
DuplicateUserRoute
Two user- or plugin-registered routes resolve to the same
(method, path) after scope-prefix resolution. Mounting both would
panic inside axum::routing::MethodRouter::merge at startup on
overlapping method routes (issue #1012), so the collision preflight
surfaces it as a recoverable RouterBuildError BEFORE any router
is mounted and names both handlers so the offending call sites are
obvious in the log.
Opaque routers registered via
AppBuilder::merge or
AppBuilder::nest are NOT introspectable
through axum’s public API, so a collision that involves one of those
routers cannot be detected up front and will still surface as an axum
startup panic — the preflight emits a tracing::warn! in that case so
operators know the check was skipped (mirrors the existing OpenAPI/MCP
merge-router warnings).
Fields
DuplicateNestPrefix
Two routers were registered at the SAME nest prefix via
AppBuilder::nest.
Every nested router is given a fallback before it is mounted
(mount_raw_routers), and axum cannot merge two method routers that
both have one — nesting the second at a prefix the first already owns
panics with “Cannot merge two MethodRouters that both have a
fallback” while the router is built.
The declared-route preflight cannot catch this: two sandboxed plugins sharing a prefix while declaring disjoint routes have no route collision at all, and are accepted right up until the second nest panics. A prefix is therefore owned by whoever nests at it first.
Fields
ConflictingRouteShape
Two user- or plugin-registered routes normalize to the SAME Axum path
shape but use DIFFERENT exact path templates — e.g. their capture names
differ (/users/{id} vs /users/{slug}) or a normal capture meets a
catch-all at the same position (/u/{id} vs /u/{*rest}).
axum’s matchit router rejects the second template as a route conflict
before method-router merging, so — unlike an exact-duplicate path,
which axum happily merges across distinct HTTP methods
(DuplicateUserRoute) — these two templates
can never coexist REGARDLESS of method. Issue #1012 surfaces the clash
here (naming both handlers and both original templates) instead of
letting the matchit conflict panic inside Router::route at startup.
Opaque AppBuilder::merge / AppBuilder::nest routers are exempt for
the same reason as DuplicateUserRoute.
Fields
LocalePrefixPathCollision
Locale-prefix routing (issue #1251) would generate a path that
collides with another route already registered at that exact path —
e.g. an app defines both /foo and /en/foo while en is a
supported locale: the bare-path redirect (mounted at every
locale-prefix-eligible path, claiming every HTTP method) already owns
/en/foo, so nesting /foo’s content under /en collides and axum
panics on the overlapping route at router-construction time. Detected
and surfaced as a build error instead (Codex review).
Trait Implementations§
Source§impl Debug for RouterBuildError
impl Debug for RouterBuildError
Source§impl Display for RouterBuildError
impl Display for RouterBuildError
impl Eq for RouterBuildError
Source§impl Error for RouterBuildError
impl Error for RouterBuildError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<SessionBackendConfigError> for RouterBuildError
impl From<SessionBackendConfigError> for RouterBuildError
Source§fn from(source: SessionBackendConfigError) -> Self
fn from(source: SessionBackendConfigError) -> Self
Source§impl PartialEq for RouterBuildError
impl PartialEq for RouterBuildError
impl StructuralPartialEq for RouterBuildError
Auto Trait Implementations§
impl Freeze for RouterBuildError
impl RefUnwindSafe for RouterBuildError
impl Send for RouterBuildError
impl Sync for RouterBuildError
impl Unpin for RouterBuildError
impl UnsafeUnpin for RouterBuildError
impl UnwindSafe for RouterBuildError
Blanket Implementations§
Source§impl<T> AggregateExpressionMethods for T
impl<T> AggregateExpressionMethods for T
Source§fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
DISTINCT modifier for aggregate functions Read moreSource§fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
ALL modifier for aggregate functions Read moreSource§fn aggregate_filter<P>(self, f: P) -> Self::Output
fn aggregate_filter<P>(self, f: P) -> Self::Output
Source§fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> AutumnCounterCaches for Twhere
T: 'static,
impl<T> AutumnCounterCaches for Twhere
T: 'static,
Source§const HAS_COUNTER_CACHES: bool = false
const HAS_COUNTER_CACHES: bool = false
Source§fn counter_caches() -> &'static [CounterCacheSpec<Self>]
fn counter_caches() -> &'static [CounterCacheSpec<Self>]
Source§impl<T> AutumnDependents for Twhere
T: ?Sized,
impl<T> AutumnDependents for Twhere
T: ?Sized,
Source§fn dependents() -> &'static [RuntimeDependentSpec]
fn dependents() -> &'static [RuntimeDependentSpec]
#[model] overrides via an inherent shadow when dependents exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoSql for T
impl<T> IntoSql for T
Source§fn into_sql<T>(self) -> Self::Expression
fn into_sql<T>(self) -> Self::Expression
self to an expression for Diesel’s query builder. Read moreSource§fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
&self to an expression for Diesel’s query builder. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T, Conn> RunQueryDsl<Conn> for T
impl<T, Conn> RunQueryDsl<Conn> for T
Source§fn execute<'conn, 'query>(
self,
conn: &'conn mut Conn,
) -> <Conn as AsyncConnectionCore>::ExecuteFuture<'conn, 'query>
fn execute<'conn, 'query>( self, conn: &'conn mut Conn, ) -> <Conn as AsyncConnectionCore>::ExecuteFuture<'conn, 'query>
Source§fn load<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
fn load<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
Source§fn load_stream<'conn, 'query, U>(
self,
conn: &'conn mut Conn,
) -> Self::LoadFuture<'conn>where
Conn: AsyncConnectionCore,
U: 'conn,
Self: LoadQuery<'query, Conn, U> + 'query,
fn load_stream<'conn, 'query, U>(
self,
conn: &'conn mut Conn,
) -> Self::LoadFuture<'conn>where
Conn: AsyncConnectionCore,
U: 'conn,
Self: LoadQuery<'query, Conn, U> + 'query,
Stream] with the returned rows. Read moreSource§fn get_result<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, LoadNext<Pin<Box<Self::Stream<'conn>>>>>
fn get_result<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, LoadNext<Pin<Box<Self::Stream<'conn>>>>>
Source§fn get_results<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
fn get_results<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
Vec with the affected rows. Read moreSource§impl<T> Scoped for T
impl<T> Scoped for T
Source§fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
ScopeQuery for this type. Resolves the
registered scope at .load() time, not here.