{"record":{"id":"f7f3577fe41065ef","repo":"linebender/druid","slug":"expected-str-found-something-else","errorCode":null,"errorMessage":"expected str, found... something else","messagePattern":"expected str, found\\.\\.\\. something else","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"druid-derive/src/attr.rs","lineNumber":283,"sourceCode":"        match self.ident {\n            FieldIdent::Named(ref s) => Ident::new(s, Span::call_site()).into(),\n            FieldIdent::Unnamed(num) => Literal::usize_unsuffixed(num).into(),\n        }\n    }\n\n    pub fn ident_string(&self) -> String {\n        match self.ident {\n            FieldIdent::Named(ref s) => s.clone(),\n            FieldIdent::Unnamed(num) => num.to_string(),\n        }\n    }\n}\n\nfn parse_lit_into_expr_path(lit: &syn::Lit) -> Result<ExprPath, Error> {\n    let string = if let syn::Lit::Str(lit) = lit {\n        lit\n    } else {\n        return Err(Error::new(\n            lit.span(),\n            \"expected str, found... something else\",\n        ));\n    };\n\n    let tokens = syn::parse_str(&string.value())?;\n    syn::parse2(tokens)\n}\n\nfn parse_lit_into_ident(lit: &syn::Lit) -> Result<Ident, Error> {\n    let ident = if let syn::Lit::Str(lit) = lit {\n        Ident::new(&lit.value(), lit.span())\n    } else {\n        return Err(Error::new(\n            lit.span(),\n            \"expected str, found... something else\",\n        ));\n    };","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/linebender/druid/blob/0f8b1195e4e073f9597f2865299c3d18f8e4005f/druid-derive/src/attr.rs#L265-L301","documentation":"parse_lit_into_expr_path converts a literal into a syn::ExprPath and only accepts string literals. When a derive attribute supplies a path value that is not a quoted string (e.g. a bare ident or integer), this compile-time error is raised at the literal's span. The humorous message acknowledges any non-str literal kind.","triggerScenarios":"Passing an unquoted path to an attribute option that expects Lit::Str and is parsed via parse_lit_into_expr_path (called from parse_ast), e.g. a lens/data option given as a bare identifier instead of \"identifier\".","commonSituations":"Forgetting quotes around path values in helper attributes, confusing string-valued options with plain path attributes, migrating from crates where paths are written unquoted.","solutions":["Quote the path value: use name = \"MyPath\" instead of name = MyPath.","Check which options expect string literals in this derive and wrap their values accordingly.","Inspect the error span — it points at the literal; make that token a string literal."],"exampleFix":"// before\n#[lens(name = my_lens)]\ncount: usize,\n// after\n#[lens(name = \"my_lens\")]\ncount: usize,","handlingStrategy":"validation","validationCode":"fn validate_path_value_is_str(opt_value: &str) -> Result<(), String> {\n    if opt_value.starts_with('\"') && opt_value.ends_with('\"') { Ok(()) }\n    else { Err(format!(\"path option must be a quoted string, got: {}\", opt_value)) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Quote every path value in derive attributes: name = \"path::Type\".","Never pass bare identifiers or numbers where the derive expects Lit::Str.","Read the error span — it names the literal that must become a string."],"tags":["derive-macro","proc-macro","type-mismatch","compile-time"],"backgroundTag":"type-mismatch","analyzedSha":"0f8b1195e4e073f9597f2865299c3d18f8e4005f","analyzedAt":"2026-09-10T14:27:34.582Z","contentChangedAt":"2026-09-10T14:27:34.582Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}