{"record":{"id":"161b4801c1e22697","repo":"Hmbown/CodeWhale","slug":"fleet-task-task-id-worker-model-must-be-a-visibl","errorCode":null,"errorMessage":"fleet task {task_id} worker.model must be a visible model id without whitespace or secrets","messagePattern":"fleet task (.+?) worker\\.model must be a visible model id without whitespace or secrets","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/task_spec.rs","lineNumber":220,"sourceCode":"\nfn is_worker_token_char(ch: char) -> bool {\n    ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.')\n}\n\nfn validate_worker_model(task_id: &str, value: Option<&str>) -> Result<()> {\n    let Some(value) = value else {\n        return Ok(());\n    };\n    let trimmed = value.trim();\n    if trimmed.is_empty() {\n        bail!(\"fleet task {task_id} worker.model cannot be empty\");\n    }\n    if trimmed != value\n        || !trimmed\n            .chars()\n            .all(|ch| ch.is_ascii_graphic() && !matches!(ch, '=' | '\\'' | '\"'))\n    {\n        bail!(\n            \"fleet task {task_id} worker.model must be a visible model id without whitespace or secrets\"\n        );\n    }\n    Ok(())\n}\n\n#[allow(clippy::too_many_arguments)]\npub fn write_fleet_artifact_ref(\n    workspace: &Path,\n    run_id: &FleetRunId,\n    task_id: &str,\n    worker_id: &str,\n    kind: FleetArtifactKind,\n    filename: &str,\n    contents: &[u8],\n    mime_type: Option<&str>,\n) -> Result<FleetArtifactRef> {\n    let rel_path = PathBuf::from(\".codewhale\")","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/fleet/task_spec.rs#L202-L238","documentation":"validate_worker_model applies the same rule as profile model hints: worker.model must have no surrounding whitespace and every character must be ASCII graphic except '=', '\\'' and '\"'. The banned characters exist so quoted ids and embedded secrets (key=value) cannot ride through a task spec.","triggerScenarios":"worker.model = \"'gpt-4o'\" (quotes pasted from docs), worker.model = \"gpt-4o # key=sk-...\" (equals sign / appended credential), or a model id containing inner whitespace or a newline.","commonSituations":"Copying quoted model ids out of documentation; appending credentials to the model string; templated specs interpolating multi-line values into worker.model.","solutions":["Write the bare model id: \"worker\": { \"model\": \"gpt-4o\" }","Remove quotes, '=' characters and whitespace from the value","Keep credentials in provider config, never in task spec model fields"],"exampleFix":"// before\n\"worker\": { \"model\": \"'claude-sonnet-4'\" }\n\n// after\n\"worker\": { \"model\": \"claude-sonnet-4\" }","handlingStrategy":"validation","validationCode":"fn is_visible_model_id(value: &str) -> bool {\n    let t = value.trim();\n    !t.is_empty()\n        && t == value\n        && t.chars().all(|c| c.is_ascii_graphic() && !matches!(c, '=' | '\\'' | '\"'))\n}","typeGuard":"function isVisibleModelId(v: string): boolean {\n  const banned = /[\\s='\"\\u0000-\\u001f]/;\n  return v.trim().length > 0 && v === v.trim() && !banned.test(v);\n}","tryCatchPattern":"if let Err(err) = load_task_spec_document(&path) {\n    if err.to_string().contains(\"visible model id\") {\n        eprintln!(\"{path:?}: worker.model must be a bare id - no quotes, spaces, or '='\");\n    }\n    return Err(err);\n}","preventionTips":["Strip surrounding quotes when copying model ids from docs","Never append credentials to model strings; keep them in provider config","Sanitize templated values for whitespace and banned characters before emitting specs"],"tags":["fleet","task-spec","worker","model-id","secrets","validation"],"backgroundTag":"invalid-model-id","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}