tokio-rs/axum · error · syn::Error
missing #[from_request(via(...))]
Error message
missing #[from_request(via(...))]
What it means
Thrown by #[derive(FromRequest)] / #[derive(FromRequestParts)] when applied to an enum (from_request/mod.rs:220). The enum branch of expand requires a #[from_request(via(SomeWrapper))] container attribute, because the generated impl converts Wrapper<Self> into Self for each variant (impl_enum_by_extracting_all_at_once). The match on (via, rejection) handles: Some(via) -> OK; (None, Some(rejection_kw)) -> 'cannot use rejection without via'; (None, _) -> this 'missing #[from_request(via(...))]' error. Field-by-field extraction is only supported on structs, not enums.
Solutions
- Add #[from_request(via(YourWrapper))] to the enum, where YourWrapper<Self>: FromRequest (e.g. a newtype wrapper, Json, Query, or a custom wrapper).
- If you wanted per-field extraction, switch the item from an enum to a struct (enums only support all-at-once extraction via a wrapper).
- If you also need a custom rejection type, supply both: #[from_request(via(Wrapper), rejection(MyRejection))].
Example fix
// before
#[derive(FromRequest, Clone)]
enum Extractor {}
// after (enum requires `via`)
#[derive(FromRequest, Clone)]
#[from_request(via(MyWrapper))]
enum Extractor {}
// or switch to a struct if field-by-field extraction is intended Defensive patterns
Strategy: validation
Validate before calling
// Safe invocation pattern: enums MUST declare `via(...)`.
#[derive(FromRequest, Clone)]
#[from_request(via(MyWrapper))] // MyWrapper<Self>: FromRequest<S>
enum Extractor {
A(A),
B(B),
}
// If you need field-by-field extraction, use a struct instead (enums do not support it):
#[derive(FromRequest)]
struct Extractor { a: A, b: B } Prevention
- Before adding #[derive(FromRequest)] to an enum, choose the wrapper type and add #[from_request(via(Wrapper))] in the same edit.
- Remember enums only support all-at-once extraction through a wrapper; switch to a struct for per-field extraction.
- If you supply rejection(...), you must also supply via(...) — rejection alone is rejected with a sibling error.
- Keep a checklist item: 'enum + FromRequest => via required'.
When it happens
Trigger: #[derive(FromRequest)] enum Extractor { ... } (or #[derive(FromRequestParts)] enum ...) with no #[from_request(via(...))] container attribute. The match falls through to (None, _) because neither via nor rejection_kw is present.
Common situations: Converting a struct-based extractor to an enum (e.g. a result-like enum) and forgetting that enums mandate via. Writing an enum newtype around another extractor without specifying the wrapper. Adding #[derive(FromRequest)] to an enum that previously only derived Clone.
Related errors
- can't infer state type, please add #
- can't infer state type, please add set it explicitly, as in…
- Missing path: #[typed_path("/foo/bar")]
- Typed paths for unit structs cannot contain captures
AI-assisted analysis of tokio-rs/axum@151cd5c123 (2026-08-11).
Data as JSON: /api/errors/5c96f1fadeba3c2c.
Report an issue: GitHub.
Appendix: source
Thrown at axum-macros/src/from_request/mod.rs:220
state_from_via(&ident, via).map(State::Custom)
})()
.unwrap_or_else(|| State::Default(syn::parse_quote!(S))),
};
match (via.map(second), rejection) {
(Some(via), rejection) => impl_enum_by_extracting_all_at_once(
&ident,
variants,
&via,
rejection.map(second).as_ref(),
&state,
tr,
),
(None, Some((rejection_kw, _))) => Err(syn::Error::new_spanned(
rejection_kw,
"cannot use `rejection` without `via`",
)),
(None, _) => Err(syn::Error::new(
Span::call_site(),
"missing `#[from_request(via(...))]`",
)),
}
}
_ => Err(syn::Error::new_spanned(item, "expected `struct` or `enum`")),
}
}
fn parse_single_generic_type_on_struct(
generics: syn::Generics,
fields: &syn::Fields,
tr: Trait,
) -> syn::Result<Option<Ident>> {
if let Some(where_clause) = generics.where_clause {
return Err(syn::Error::new_spanned(
where_clause,
format_args!("#[derive({tr})] doesn't support structs with `where` clauses"),View on GitHub (pinned to 151cd5c123)