{"id":"07d5e1fca44ea8c8","repo":"actix/actix-web","slug":"invalid-service-definition-expected-method","errorCode":null,"errorMessage":"invalid service definition, expected #[<method>(\"<path>\")]","messagePattern":"invalid service definition, expected #\\[<method>\\(\"<path>\"\\)\\]","errorType":"exception","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"actix-web-codegen/src/route.rs","lineNumber":21,"sourceCode":"use actix_router::ResourceDef;\nuse proc_macro::TokenStream;\nuse proc_macro2::{Span, TokenStream as TokenStream2};\nuse quote::{quote, ToTokens, TokenStreamExt};\nuse syn::{punctuated::Punctuated, Ident, LitStr, Path, Token};\n\nuse crate::input_and_compile_error;\n\n#[derive(Debug)]\npub struct RouteArgs {\n    pub(crate) path: syn::LitStr,\n    pub(crate) options: Punctuated<syn::MetaNameValue, Token![,]>,\n}\n\nimpl syn::parse::Parse for RouteArgs {\n    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {\n        // path to match: \"/foo\"\n        let path = input.parse::<syn::LitStr>().map_err(|mut err| {\n            err.combine(syn::Error::new(\n                err.span(),\n                r#\"invalid service definition, expected #[<method>(\"<path>\")]\"#,\n            ));\n\n            err\n        })?;\n\n        // verify that path pattern is valid\n        let _ = ResourceDef::new(path.value());\n\n        // if there's no comma, assume that no options are provided\n        if !input.peek(Token![,]) {\n            return Ok(Self {\n                path,\n                options: Punctuated::new(),\n            });\n        }\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/actix/actix-web/blob/937960ca67f20e14ffe2a075bf6d4593502be12c/actix-web-codegen/src/route.rs#L3-L39","documentation":"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>\")]`.","triggerScenarios":"Writing `#[get(foo)]` (bare ident), `#[get(/foo)]` (unquoted), or `#[get(\"/foo\".to_string())]` (expression) instead of a quoted path string.","commonSituations":"Forgetting quotes, using a `const` path value, or trying to interpolate a variable into the path.","solutions":["Wrap the path in double quotes: `#[get(\"/foo\")]`.","If you need a constant path, note that macros require literals — inline the string literal directly.","Ensure there are no stray tokens before the path string."],"exampleFix":"// before\n#[get(foo)]\nasync fn handler() -> HttpResponse { ... }\n\n// after\n#[get(\"/foo\")]\nasync fn handler() -> HttpResponse { ... }","handlingStrategy":"validation","validationCode":"// The path must be a string literal at the macro site. There is no runtime API.\n// Lint rule of thumb: the first token inside #[<method>(...)] must be \"...\".","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always quote route paths.","Do not attempt to interpolate variables into macro path arguments."],"tags":["rust","actix","actix-web","macro","compile-time","routing"],"analyzedSha":"937960ca67f20e14ffe2a075bf6d4593502be12c","analyzedAt":"2026-08-06T01:15:46.978Z","schemaVersion":2}