actix/actix-web · error · syn::Error

invalid service definition, expected #[<method>("<path>")]

Error message

invalid service definition, expected #[<method>("<path>")]

What it means

Method/route macros expect a string-literal path as the first argument. At actix-web-codegen/src/route.rs:20-27 the macro tries `input.parse::<syn::LitStr>()` for the path; if the first token is not a string literal it appends this guidance message. The form is `#[<method>("<path>")]`.

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 937960ca67)

Solutions

  1. Wrap the path in double quotes: `#[get("/foo")]`.
  2. If you need a constant path, note that macros require literals — inline the string literal directly.
  3. Ensure there are no stray tokens before the path string.

Example fix

// before
#[get(foo)]
async fn handler() -> HttpResponse { ... }

// after
#[get("/foo")]
async fn handler() -> HttpResponse { ... }
Defensive patterns

Strategy: validation

Validate before calling

// The path must be a string literal at the macro site. There is no runtime API.
// Lint rule of thumb: the first token inside #[<method>(...)] must be "...".

Prevention

When it happens

Trigger: Writing `#[get(foo)]` (bare ident), `#[get(/foo)]` (unquoted), or `#[get("/foo".to_string())]` (expression) instead of a quoted path string.

Common situations: Forgetting quotes, using a `const` path value, or trying to interpolate a variable into the path.

Related errors


AI-assisted analysis of actix/actix-web@937960ca67 (2026-08-06). Data as JSON: /data/errors/07d5e1fca44ea8c8.json. Report an issue: GitHub.