{"record":{"id":"d59a916f2aec6f56","repo":"Hmbown/CodeWhale","slug":"agent-profile-provider-must-be-a-simple-provide","errorCode":null,"errorMessage":"agent profile {} provider must be a simple provider id","messagePattern":"agent profile (.+?) provider must be a simple provider id","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/profile.rs","lineNumber":562,"sourceCode":"        );\n    }\n    Ok(())\n}\n\n/// Validate an explicit `provider` field as a safe provider id (#4093).\n///\n/// Built-in providers are accepted by the runtime vocabulary, and user-named\n/// OpenAI-compatible custom providers are accepted as simple tokens so the\n/// launch path can resolve `[providers.<id>]` from the session config (#3965).\n/// This field remains the ONLY place a profile's provider is established:\n/// callers never infer it from `model` (EPIC #2608).\nfn validate_agent_profile_provider(path: &Path, value: &str) -> Result<()> {\n    let trimmed = value.trim();\n    if trimmed.is_empty() {\n        bail!(\"agent profile {} provider cannot be empty\", path.display());\n    }\n    if trimmed != value || !trimmed.chars().all(is_agent_profile_token_char) {\n        bail!(\n            \"agent profile {} provider must be a simple provider id\",\n            path.display()\n        );\n    }\n    Ok(())\n}\n\nfn normalize_agent_profile_reasoning_effort(\n    path: &Path,\n    value: Option<&str>,\n) -> Result<Option<String>> {\n    let Some(value) = non_empty_trimmed(value) else {\n        return Ok(None);\n    };\n    if matches!(\n        value.to_ascii_lowercase().as_str(),\n        \"inherit\" | \"parent\" | \"same\" | \"current\" | \"default\" | \"unset\"\n    ) {","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/fleet/profile.rs#L544-L580","documentation":"validate_agent_profile_provider (crates/tui/src/fleet/profile.rs:562) requires the provider value to be a 'simple provider id': no leading/trailing whitespace and only characters accepted by is_agent_profile_token_char. Anything else — padded strings, slashes, dots, spaces, unicode — is rejected so the launch path can resolve `[providers.<id>]` from the session config (#3965).","triggerScenarios":"agent_profile_from_toml encounters a provider value that differs from its trimmed form (leading/trailing spaces) or contains characters outside the allowed token charset.","commonSituations":"Writing `provider = \"openai \"` with a trailing space from an editor; using a qualified name like `openai/gpt-4` or a URL as provider; pasting model strings into the provider field.","solutions":["Trim the provider value and use a bare token (letters/digits/dash/underscore as allowed by is_agent_profile_token_char)","Use the provider's registry id exactly as it appears under [providers.<id>] in the session config","Do not encode model names, paths, or URLs in the provider field"],"exampleFix":"# before\nprovider = \"openai/gpt-4\"\n# after\nprovider = \"openai\"","handlingStrategy":"validation","validationCode":"fn is_simple_provider_id(s: &str) -> bool {\n    let t = s.trim();\n    t == s && !t.is_empty() && t.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')\n}","typeGuard":"fn is_simple_token(s: &str) -> bool { !s.trim().is_empty() && s.trim() == s && s.chars().all(is_agent_profile_token_char) }","tryCatchPattern":"match agent_profile_from_toml(path) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"must be a simple provider id\") => {\n        eprintln!(\"{}: provider must be a bare id, no spaces/paths\", path.display());\n        return;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use the provider's registry id exactly as it appears under [providers.<id>]","Never put model names, URLs, or qualified paths in the provider field","Trim values when generating profiles programmatically"],"tags":["config","fleet","validation","rust"],"backgroundTag":"invalid-identifier-format","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}