{"record":{"id":"cceaad0b3ab47182","repo":"Hmbown/CodeWhale","slug":"fleet-task-names-custom-provider-provider-id-but-a-provider","errorCode":null,"errorMessage":"Fleet task `{}` names custom provider=`{provider_id}`, but a provider name alone does not prove its endpoint or model; attach the live route config before creating the run","messagePattern":"Fleet task `(.+?)` names custom provider=`(.+?)`, but a provider name alone does not prove its endpoint or model; attach the live route config before creating the run","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/worker_runtime.rs","lineNumber":293,"sourceCode":"    for task in tasks {\n        let agent_profile = resolve_task_agent_profile(task, agent_profiles)?;\n        let agent_profile = agent_profile.as_deref();\n        let (model, source) =\n            effective_fleet_model_with_source(run_model, task.worker.as_ref(), agent_profile);\n        let pinned_model = matches!(source, \"task.model\" | \"agent_profile.model\");\n        let explicit_provider = explicit_fleet_provider_id(agent_profile);\n        if config.is_none() && explicit_provider.is_none() {\n            bail!(\n                \"Fleet task `{}` has no provider authority for model `{model}` (source={source}); attach the resolved route config or set the agent profile provider explicitly\",\n                task.id,\n            );\n        }\n        if config.is_none()\n            && let Some(provider_id) = explicit_provider.as_deref()\n            && ApiProvider::parse(provider_id)\n                .is_none_or(|provider| provider == ApiProvider::Custom)\n        {\n            bail!(\n                \"Fleet task `{}` names custom provider=`{provider_id}`, but a provider name alone does not prove its endpoint or model; attach the live route config before creating the run\",\n                task.id,\n            );\n        }\n        if pinned_model && explicit_provider.is_none() {\n            let config = config.expect(\"provider authority checked above\");\n            let (provider, base_url) = (config.api_provider(), config.active_route_base_url());\n            if let Err(reason) =\n                crate::route_runtime::validate_unpinned_model_provider(provider, &model, &base_url)\n            {\n                bail!(\"Fleet task `{}`: {reason} (source={source})\", task.id);\n            }\n        }\n\n        let route = resolve_fleet_route_with_config(task, agent_profiles, session_model, config);\n        let provider = explicit_provider\n            .map(|provider| format!(\"provider=`{provider}`\"))\n            .unwrap_or_else(|| {","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/fleet/worker_runtime.rs#L275-L311","documentation":"Fleet route validation rejects a task that names a provider whose id parses as ApiProvider::Custom (or fails to parse) while no live route config is attached. A provider name alone does not prove a working endpoint or model list, so run creation requires the resolved route config.","triggerScenarios":"validate_fleet_task_routes with config=None and the agent profile's explicit provider id being \"custom\" (or an unparseable provider id) for the task's effective model.","commonSituations":"Pointing an agent profile at a self-hosted/custom endpoint by name only, without the route config carrying the base URL and credentials; typos in provider ids that fail ApiProvider::parse; environments where route config was intentionally not shipped (configless fleet).","solutions":["Attach the live resolved route config to the run.","Switch the profile to a built-in provider id that needs no config proof.","Correct the provider id typo so it parses to a known provider."],"exampleFix":"// before\nprovider: \"custom\"  // no route config attached\n// after\nrun.create(..., route_config=live_config)  // config proves the custom endpoint","handlingStrategy":"validation","validationCode":"fn custom_provider_needs_config(config: Option<&RouteConfig>, provider: Option<&str>) -> bool { config.is_none() && provider.map_or(false, |p| ApiProvider::parse(p).is_none_or(|ap| ap == ApiProvider::Custom)) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ship the live route config with any custom provider","Avoid provider-name-only references to custom endpoints","Validate provider ids parse to known built-ins before configless runs"],"tags":["fleet","provider","routing"],"backgroundTag":"missing-required-config","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"}