{"record":{"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":"validation","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/4d435abc281842f3cbee165b6cde739e001d3a25/actix-web-codegen/src/route.rs#L3-L39","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n#[get(/users)]\nasync fn users() -> impl Responder { ... }\n\n// after\n#[get(\"/users\")]\nasync fn users() -> impl Responder { ... }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// This is a compile-time error. Ensure the path is a string literal:\n// #[get(\"/users\")] — correct\n// #[get(/users)]  — incorrect (missing quotes)\n// cargo check will report this error with the exact location.","tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","actix-web","codegen","routing","compile-time","macro"],"backgroundTag":null,"analyzedSha":"4d435abc281842f3cbee165b6cde739e001d3a25","analyzedAt":"2026-08-09T01:01:40.926Z","contentChangedAt":"2026-08-09T01:01:40.926Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}