actix/actix-web · error · syn::Error
The #[routes] macro requires at least one `#
Error message
The #[routes] macro requires at least one `#[<method>(..)]` attribute.
What it means
This compile-time error fires when `#[routes]` is applied to a function that has no HTTP method attribute (`#[get(...)]`, `#[post(...)]`, etc.) attached. The `with_methods` function scans all attributes on the function for known method types at line 518-523; if none are found, `methods` is empty and the check at line 533-540 fails.
Solutions
- Add at least one HTTP method attribute below `#[routes]`: `#[get("/path")]`, `#[post("/path")]`, etc.
- If the function only needs one route, remove `#[routes]` and use a single method attribute directly
- Check for typos in method attribute names; they must be lowercase: `get`, `post`, `put`, `delete`, etc.
Example fix
// before
#[routes]
async fn handler() -> impl Responder { ... }
// after
#[routes]
#[get("/items")]
#[post("/items")]
async fn handler() -> impl Responder { ... } Defensive patterns
Strategy: type-guard
Type guard
// Compile-time error. #[routes] requires at least one method attribute:
// #[routes]
// #[get("/items")] — must have this or another method attribute
// async fn handler() { ... } Prevention
- Always add at least one #[get(...)], #[post(...)], etc. attribute under #[routes]
- Use lowercase method names (get, post, put, delete, patch, head, options, trace, connect)
- If only one route is needed, skip #[routes] and use a single method attribute directly
When it happens
Trigger: Writing `#[routes]` on a function that only has non-routing attributes, or forgetting to add a method attribute below it. For example, `#[routes]` followed by `#[middleware(...)]` but no `#[get(...)]`.
Common situations: Developers who add `#[routes]` first planning to add method attributes later, or who remove the only method attribute without removing `#[routes]`. Also happens when the method attribute name is misspelled (e.g., `#[Get("/")]` with uppercase).
Related errors
- argument to scope macro is not a string literal, expected…
- invalid service definition, expected #
- missing arguments for scope macro, expected…
- Multiple paths specified! There should be only one.
- #[scope] macro must be attached to a module
AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09).
Data as JSON: /api/errors/ac03d9ff8296fe2f.
Report an issue: GitHub.
Appendix: source
Thrown at actix-web-codegen/src/route.rs:536
for attr in std::mem::take(&mut ast.attrs) {
match MethodType::from_path(attr.path()) {
Ok(method) => methods.push((method, attr)),
Err(_) => ast.attrs.push(attr),
}
}
let methods = match methods
.into_iter()
.map(|(method, attr)| {
attr.parse_args()
.and_then(|args| Args::new(args, Some(method)))
})
.collect::<Result<Vec<_>, _>>()
{
Ok(methods) if methods.is_empty() => {
return input_and_compile_error(
input,
syn::Error::new(
Span::call_site(),
"The #[routes] macro requires at least one `#[<method>(..)]` attribute.",
),
)
}
Ok(methods) => methods,
Err(err) => return input_and_compile_error(input, err),
};
match Route::multiple(methods, ast) {
Ok(route) => route.into_token_stream().into(),
// on macro related error, make IDEs happy; see fn docs
Err(err) => input_and_compile_error(input, err),
}
}
View on GitHub (pinned to 4d435abc28)