actix/actix-web · error · syn::Error
scopes should not have trailing slashes; see…
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
This compile-time error fires when the scope prefix string ends with a trailing slash (e.g., `"/api/"`). The check at line 34 detects this and rejects it because trailing slashes in scope prefixes cause non-obvious routing problems — the combined route paths end up with double slashes or unexpected matching behavior.
Solutions
- Remove the trailing slash from the scope prefix: `#[scope("/api")]`
- The individual route paths inside the scope should start with `/`: `#[get("/users")]` produces the combined path `/api/users`
- If the root of the scope needs to be handled, use `#[get("")]` inside the scope
Example fix
// before
#[scope("/api/")]
mod api {
#[get("/users")]
async fn users() -> impl Responder { ... }
}
// after
#[scope("/api")]
mod api {
#[get("/users")]
async fn users() -> impl Responder { ... }
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the scope prefix does not end with a trailing slash.
// This is a compile-time check, but you can apply the same rule to runtime paths.
fn validate_scope_prefix(prefix: &str) -> Result<(), String> {
if prefix.ends_with('/') {
Err(format!("Scope prefix '{}' has a trailing slash", prefix))
} else {
Ok(())
}
} Type guard
fn has_no_trailing_slash(prefix: &str) -> bool {
!prefix.ends_with('/')
} Prevention
- Never include a trailing slash in scope prefixes: use #[scope("/api")] not #[scope("/api/")]
- Individual routes inside the scope should start with '/': #[get("/users")]
- For the scope root, use #[get("")] inside the scoped module
When it happens
Trigger: Writing `#[scope("/api/")]` with a trailing slash. The combined route paths would become `"/api//users"` which can lead to incorrect matches or 404s.
Common situations: Copy-pasting a URL prefix that includes a trailing slash, or following a convention from another framework where trailing slashes are the norm.
Related errors
- argument to scope macro is not a string literal, expected…
- missing arguments for scope macro, expected…
- #[scope] macro must be attached to a module
- invalid service definition, expected #
- Multiple paths specified! There should be only one.
AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09).
Data as JSON: /api/errors/b73af54e6da4b828.
Report an issue: GitHub.
Appendix: 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 4d435abc28)