{"record":{"id":"45a65482167920ef","repo":"aaif-goose/goose","slug":"invalid-provider-id-id","errorCode":null,"errorMessage":"Invalid provider id: {id}","messagePattern":"Invalid provider id: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/goose-providers/src/declarative.rs","lineNumber":399,"sourceCode":"    }\n\n    fn placeholder_var_names(template: &str) -> Vec<String> {\n        template\n            .split(\"${\")\n            .skip(1)\n            .filter_map(|chunk| chunk.split_once('}'))\n            .map(|(name, _)| name.to_string())\n            .collect()\n    }\n\n    fn validate_provider_id(id: &str) -> Result<()> {\n        let mut chars = id.chars();\n        let Some(first) = chars.next() else {\n            anyhow::bail!(\"Invalid provider id: provider id cannot be empty\");\n        };\n\n        if !(first.is_ascii_lowercase() || first.is_ascii_digit() || first == '_') {\n            anyhow::bail!(\"Invalid provider id: {id}\");\n        }\n\n        if chars.all(|ch| ch.is_ascii_lowercase() || ch.is_ascii_digit() || ch == '_' || ch == '-')\n        {\n            Ok(())\n        } else {\n            anyhow::bail!(\"Invalid provider id: {id}\")\n        }\n    }\n\n    #[test]\n    fn expose_declarative_providers_enumerates_all_bundled_json_files() {\n        let enumerated: HashSet<_> = fixed_provider_config_entries()\n            .into_iter()\n            .map(|(path, _)| path.to_string())\n            .collect();\n        let bundled: HashSet<_> = FIXED_PROVIDERS\n            .files()","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-providers/src/declarative.rs#L381-L417","documentation":"validate_provider_id (in declarative.rs's #[cfg(test)] module) rejects a provider id whose first character is not an ASCII lowercase letter, digit, or underscore. The id is the provider JSON's 'name' field, and this first-character rule is stricter than the rest of the string (a leading hyphen is not allowed even though hyphens are fine later). It fires from bundled-provider validation tests, not at runtime.","triggerScenarios":"A bundled provider JSON with \"name\": \"-gateway\", \"name\": \".local\", \"name\": \"MyProvider\" (uppercase first letter), or any leading symbol/punctuation — caught when cargo test runs all_bundled_providers_are_valid.","commonSituations":"Team naming conventions that start ids with uppercase brand names or hyphenated prefixes; porting provider ids from other ecosystems (npm scopes like '@acme/x' or '.local' style) that don't match goose's slug rules.","solutions":["Rename so the id starts with a lowercase letter, digit, or underscore: 'my-provider' instead of 'My-provider' or '-provider'","If the display name needs capitals/style, keep 'name' slug-form and put the pretty text in 'display_name'","Re-run the declarative provider tests after fixing"],"exampleFix":"// before\n{ \"name\": \"AcmeGateway\", \"display_name\": \"Acme\", ... }\n\n// after\n{ \"name\": \"acme_gateway\", \"display_name\": \"Acme Gateway\", ... }","handlingStrategy":"validation","validationCode":"fn id_first_char_ok(id: &str) -> bool {\n    id.chars().next().is_some_and(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_')\n}","typeGuard":"fn is_valid_provider_id(id: &str) -> bool {\n    !id.is_empty()\n        && id.starts_with(|c: char| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_')\n        && id.chars().skip(1).all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '-')\n}","tryCatchPattern":"// In generator scripts, fix ids automatically instead of failing:\nlet id = id.to_ascii_lowercase().trim_start_matches(['-', '.']).to_string();\nassert!(is_valid_provider_id(&id));","preventionTips":["Never start ids with a hyphen, dot, or uppercase letter; prefix-digit-underscore are the safe first chars","Put branded capitalization in display_name, never in name/id","Add a regex lint ([a-z0-9_][a-z0-9_-]*) to your provider-config linter"],"tags":["provider-setup","json-config","validation","testing"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}