tokio-rs/axum · error · syn::Error
can't infer state type, please add #[{attr_name}(state = MyS
Error message
can't infer state type, please add #[{attr_name}(state = MyStateType)] attribute What it means
Thrown by #[derive(FromRequest)] / #[derive(FromRequestParts)] on a struct (from_request/mod.rs:154). The macro infers the state type by scanning fields: infer_state_type_from_field_types collects inner types of any State<T> field, and infer_state_type_from_field_attributes collects the field type of any #[from_request(via(State))] field. If these yield two or more distinct candidate types, state becomes State::CannotInfer. The macro still emits the generated impl (with an unimplemented!() body so downstream errors are visible) followed by this compile_error.
Source
Thrown at axum-macros/src/from_request/mod.rs:154
fields,
&via,
rejection.as_ref(),
generic_ident.as_ref(),
&state,
tr,
)?,
(None, rejection) => {
error_on_generic_ident(generic_ident, tr)?;
impl_struct_by_extracting_each_field(&ident, &fields, rejection, &state, tr)?
}
};
if matches!(state, State::CannotInfer) {
let attr_name = match tr {
Trait::FromRequest => "from_request",
Trait::FromRequestParts => "from_request_parts",
};
let compile_error = syn::Error::new(
Span::call_site(),
format_args!(
"can't infer state type, please add \
`#[{attr_name}(state = MyStateType)]` attribute",
),
)
.into_compile_error();
Ok(quote! {
#trait_impl
#compile_error
})
} else {
Ok(trait_impl)
}
}
syn::Item::Enum(item) => {
let syn::ItemEnum {View on GitHub (pinned to 151cd5c123)
Solutions
- Add the container attribute naming the router's root state: #[from_request(state = AppState)] (or #[from_request_parts(state = AppState)]).
- Make all State<T> / #[from_request(via(State))] fields agree on the same inner type.
- Drop the redundant State<_> field and obtain sub-state via FromRef instead.
Example fix
// before
#[derive(FromRequest)]
struct Extractor {
inner_state: State<AppState>,
other_state: State<OtherState>,
}
// after
#[derive(FromRequest)]
#[from_request(state = AppState)]
struct Extractor {
inner_state: State<AppState>,
other_state: State<OtherState>,
} Defensive patterns
Strategy: validation
Validate before calling
// Safe invocation pattern: if a FromRequest struct has fields whose inferred
// state types could disagree, always set the container `state = ...`.
#[derive(FromRequest)]
#[from_request(state = AppState)] // names the router root state explicitly
struct Extractor {
inner_state: State<AppState>,
other_state: State<OtherState>,
}
// Single-state structs infer fine without the attribute:
#[derive(FromRequest)]
struct Simple { s: State<AppState> } Prevention
- Audit every #[derive(FromRequest)]/FromRequestParts struct: count distinct inner types across State<T> fields and #[from_request(via(State))] fields; if >1, add #[from_request(state = ...)].
- Keep all State<_> fields of a derived extractor anchored to the same root state; pull sub-state through FromRef.
- When refactoring state types, re-check derived extractors that referenced the old type.
- Treat #[from_request(via(State))] on a field as another state-type candidate — it counts toward inference ambiguity.
When it happens
Trigger: #[derive(FromRequest)] struct Extractor { a: State<AppState>, b: State<OtherState> } with no #[from_request(state = ...)] container attribute, where AppState and OtherState are different types. Also triggered when a State<A> field and a #[from_request(via(State))] field: B disagree (A != B), or when via(State) on the container combined with conflicting field-level State<...> types yields more than one candidate.
Common situations: Building a composite extractor that aggregates several sub-extractors each carrying their own state. Mixing a State<T> field with a #[from_request(via(State))] field on the same struct. Migrating a struct from one state type to another and leaving a stale field behind.
Related errors
- missing #[from_request(via(...))]
- 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/5770f04f974347ae.
Report an issue: GitHub.