Hmbown/CodeWhale · error
A pinned task provider requires an explicit model
Error message
A pinned task provider requires an explicit model
What it means
When a NewTaskRequest pins a provider (model_provider or model_provider_id set), the request must also name an explicit model. The worker projects runtime policy with a concrete model, so an ambiguous provider-only request is refused at admission rather than failing later after the task sat in the durable queue.
Solutions
- Set req.model to a concrete model name whenever req.model_provider/model_provider_id is set
- Clear the provider fields if the intent is to use the default provider/model resolution
- Validate the (provider, model) pair in the caller/UI before submitting the request
- Ensure templates/config migrations that add a provider also carry a model
Example fix
// before
let req = NewTaskRequest { model_provider: Some("openai"), model: None, .. };
// after
let req = NewTaskRequest {
model_provider: Some("openai"),
model: Some("gpt-4o".into()),
..
}; Defensive patterns
Strategy: validation
Validate before calling
anyhow::ensure!(req.model_provider.is_none() && req.model_provider_id.is_none() || req.model.as_deref().map_or(false, |m| !m.trim().is_empty()), "pinned provider needs an explicit model");
Prevention
- Treat (provider, model) as one atomic selection in UI state
- Keep config templates with provider pins carrying model pins too
- Clear both provider fields together when reverting to defaults
When it happens
Trigger: Calling add_task_with_id with model_provider/model_provider_id set but model None or empty/whitespace after trim.
Common situations: Automation rules that pin a provider but forget the model field; UI state where the model selector was cleared but the provider persisted; config templates carrying provider-only overrides.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Failed to update setting: invalid cost currency
- Failed to update setting: invalid mode
- Failed to update setting: invalid ocean treatment
- Failed to update setting: invalid permission posture
- Failed to update setting: invalid status indicator
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1879009f101d263a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/task_manager.rs:1687
/// Enqueue using a preallocated id. This is crate-visible only for the
/// model tool's register-before-work transaction.
pub(crate) async fn add_task_with_id(
&self,
req: NewTaskRequest,
task_id: String,
) -> Result<TaskRecord> {
let prompt = req.prompt.trim().to_string();
if prompt.is_empty() {
bail!("Task prompt cannot be empty");
}
if (req.model_provider.is_some() || req.model_provider_id.is_some())
&& req
.model
.as_deref()
.is_none_or(|model| model.trim().is_empty())
{
bail!("A pinned task provider requires an explicit model");
}
// The worker runs this same projection when it opens the task's
// thread. Running it here as well refuses an unknown mode or posture
// at the boundary the request crossed, instead of after the task has
// sat in the durable queue and a worker has claimed it.
crate::runtime_policy::RuntimePolicyProjection::from_request(
req.mode
.as_deref()
.filter(|mode| !mode.trim().is_empty())
.unwrap_or(&self.cfg.default_mode),
req.permission_posture.as_deref(),
req.auto_approve,
)?;
validate_preallocated_task_id(&task_id)?;
let task = TaskRecord {
schema_version: CURRENT_TASK_SCHEMA_VERSION,
// 16 random hex chars (was 8; ~60 bits of entropy once UUIDv4'sView on GitHub (pinned to 73e0f67d83)