{"record":{"id":"a5649bd8b2d6aaaf","repo":"Hmbown/CodeWhale","slug":"agent-profile-provider-cannot-be-empty","errorCode":null,"errorMessage":"agent profile {} provider cannot be empty","messagePattern":"agent profile (.+?) provider cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/profile.rs","lineNumber":559,"sourceCode":"        bail!(\n            \"agent profile {} model must be a visible model id without whitespace or secrets\",\n            path.display()\n        );\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!(","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/fleet/profile.rs#L541-L577","documentation":"Agent profile TOML files must name a provider id explicitly. validate_agent_profile_provider in crates/tui/src/fleet/profile.rs rejects a provider value that is empty or whitespace-only, because the field is the ONLY place a profile's provider is established — callers never infer it from the model name (EPIC #2608).","triggerScenarios":"Calling agent_profile_from_toml on a profile whose `provider` key is missing/empty or set to \"\" or whitespace; validation happens at crates/tui/src/fleet/profile.rs:559.","commonSituations":"Hand-written fleet profile TOML that omits `provider`; copy-pasting a profile and deleting the provider line assuming the model string implies it; templating tools emitting blank provider values.","solutions":["Set a non-empty `provider = \"<provider-id>\"` in the profile TOML","Use a simple provider id that exists in the session config so `[providers.<id>]` resolves at launch","Re-run agent_profile_from_toml after fixing the file"],"exampleFix":"# before\nprovider = \"\"\n# after\nprovider = \"anthropic\"","handlingStrategy":"validation","validationCode":"fn provider_ok(v: Option<&str>) -> bool { v.map(|s| !s.trim().is_empty()).unwrap_or(false) }\nassert!(provider_ok(Some(\"anthropic\")));\nassert!(!provider_ok(Some(\"\")));","typeGuard":"fn has_provider(p: &AgentProfileToml) -> bool { p.provider.as_deref().map(|s| !s.trim().is_empty()).unwrap_or(false) }","tryCatchPattern":"match agent_profile_from_toml(path) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"provider cannot be empty\") => {\n        eprintln!(\"{}: add a non-empty `provider` key\", path.display());\n        return;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always set `provider` explicitly in every agent profile TOML","Never rely on the model string to imply the provider — the field is the sole source of provider identity (EPIC #2608)","Validate profiles in CI before committing them"],"tags":["config","fleet","validation","rust"],"backgroundTag":"empty-required-field","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"}