actix/actix-web · error · syn::Error
scopes should not have trailing slashes; see https://docs.rs
Error message
scopes should not have trailing slashes; see https://docs.rs/actix-web/4/actix_web/struct.Scope.html#avoid-trailing-slashes
What it means
Scope prefixes must not end with a `/`. At actix-web-codegen/src/scope.rs:34-42 the macro rejects a trailing slash because it produces non-obvious routing bugs (double slashes when concatenated with route paths). The message links to the official guidance on avoiding trailing slashes.
Source
Thrown at actix-web-codegen/src/scope.rs:38
Span::call_site(),
"missing arguments for scope macro, expected: #[scope(\"/prefix\")]",
));
}
let scope_prefix = syn::parse::<syn::LitStr>(args.clone()).map_err(|err| {
syn::Error::new(
err.span(),
"argument to scope macro is not a string literal, expected: #[scope(\"/prefix\")]",
)
})?;
let scope_prefix_value = scope_prefix.value();
if scope_prefix_value.ends_with('/') {
// trailing slashes cause non-obvious problems
// it's better to point them out to developers rather than
return Err(syn::Error::new(
scope_prefix.span(),
"scopes should not have trailing slashes; see https://docs.rs/actix-web/4/actix_web/struct.Scope.html#avoid-trailing-slashes",
));
}
let mut module = syn::parse::<syn::ItemMod>(input).map_err(|err| {
syn::Error::new(err.span(), "#[scope] macro must be attached to a module")
})?;
// modify any routing macros (method or route[s]) attached to
// functions by prefixing them with this scope macro's argument
if let Some((_, items)) = &mut module.content {
for item in items {
if let syn::Item::Fn(fun) = item {
fun.attrs = fun
.attrs
.iter()
.map(|attr| modify_attribute_with_scope(attr, &scope_prefix_value))View on GitHub (pinned to 937960ca67)
Solutions
- Remove the trailing slash from the scope prefix: `#[scope("/api")]`.
- Leave trailing slashes off inner route paths too; rely on the scope prefix + route path joining.
Example fix
// before
#[scope("/api/")]
mod api {
#[get("/users")]
async fn users() -> HttpResponse { ... }
}
// after
#[scope("/api")]
mod api {
#[get("/users")]
async fn users() -> HttpResponse { ... }
} Defensive patterns
Strategy: validation
Validate before calling
// Compile-time only. Reject trailing slashes in scope prefixes.
// Quick check: ensure the prefix does not end with '/'.
fn no_trailing_slash(p: &str) -> bool { !p.ends_with('/') }
// assert!(no_trailing_slash("/api"));
// assert!(!no_trailing_slash("/api/")); Prevention
- Adopt a convention of no trailing slashes anywhere in route/scope paths.
- When copying URLs from browsers/config, strip the trailing slash first.
When it happens
Trigger: `#[scope("/api/")]` — prefix ending in `/`. The macro then concatenates this with inner route paths like `"/users"`, yielding `"/api//users"`.
Common situations: Copying a base URL with a trailing slash from a config/browser, or assuming the framework normalizes slashes.
Related errors
- invalid service definition, expected #[<method>("<path>")]
- Multiple paths specified! There should be only one.
- The #[route(..)] macro requires at least one `method` attrib
- The #[routes] macro requires at least one `#[<method>(..)]`
- missing arguments for scope macro, expected: #[scope("/prefi
AI-assisted analysis of actix/actix-web@937960ca67 (2026-08-06).
Data as JSON: /data/errors/b73af54e6da4b828.json.
Report an issue: GitHub.