actix/actix-web · error · syn::Error
invalid service definition, expected #
Error message
invalid service definition, expected #[<method>("<path>")] What it means
This compile-time error fires when the first argument inside a route macro attribute (e.g., `#[get(...)]`, `#[post(...)]`) cannot be parsed as a string literal. The macro expects the form `#[<method>("<path>")]` and tries to parse the tokens as `syn::LitStr` at line 20; if the token is a number, identifier, or expression, parsing fails with this message.
Solutions
- Wrap the path in double quotes: `#[get("/users")]` instead of `#[get(/users)]`
- Do not use variables or constants as the path argument; use a string literal
- Ensure there are no stray characters or missing quotes in the attribute
Example fix
// before
#[get(/users)]
async fn users() -> impl Responder { ... }
// after
#[get("/users")]
async fn users() -> impl Responder { ... } Defensive patterns
Strategy: type-guard
Type guard
// This is a compile-time error. Ensure the path is a string literal:
// #[get("/users")] — correct
// #[get(/users)] — incorrect (missing quotes)
// cargo check will report this error with the exact location. Prevention
- Always wrap route paths in double quotes: #[get("/path")]
- Use an IDE or rust-analyzer to catch syntax issues as you type
- Follow the actix-web routing examples from the official docs
When it happens
Trigger: Writing `#[get(/users)]` (path without quotes), `#[get(42)]` (non-string), or `#[get(foo)]` (bare identifier). Any route macro where the path argument is not a quoted string literal triggers this.
Common situations: Forgetting to wrap the route path in quotes, or attempting to use a constant/variable as the path. Most common when developers are used to other frameworks that accept bare paths.
Related errors
- argument to scope macro is not a string literal, expected…
- missing arguments for scope macro, expected…
- Multiple paths specified! There should be only one.
- #[scope] macro must be attached to a module
- scopes should not have trailing slashes; see…
AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09).
Data as JSON: /api/errors/07d5e1fca44ea8c8.
Report an issue: GitHub.
Appendix: source
Thrown at actix-web-codegen/src/route.rs:21
use actix_router::ResourceDef;
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, ToTokens, TokenStreamExt};
use syn::{punctuated::Punctuated, Ident, LitStr, Path, Token};
use crate::input_and_compile_error;
#[derive(Debug)]
pub struct RouteArgs {
pub(crate) path: syn::LitStr,
pub(crate) options: Punctuated<syn::MetaNameValue, Token![,]>,
}
impl syn::parse::Parse for RouteArgs {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
// path to match: "/foo"
let path = input.parse::<syn::LitStr>().map_err(|mut err| {
err.combine(syn::Error::new(
err.span(),
r#"invalid service definition, expected #[<method>("<path>")]"#,
));
err
})?;
// verify that path pattern is valid
let _ = ResourceDef::new(path.value());
// if there's no comma, assume that no options are provided
if !input.peek(Token![,]) {
return Ok(Self {
path,
options: Punctuated::new(),
});
}
View on GitHub (pinned to 4d435abc28)