{"record":{"id":"a7bf1ca34f978b83","repo":"Hmbown/CodeWhale","slug":"fleet-task-task-id-field-must-be-one-printable-selector-no","errorCode":null,"errorMessage":"fleet task {task_id} {field} must be one printable selector no longer than {MAX_FLEET_NAME_BYTES} bytes","messagePattern":"fleet task (.+?) (.+?) must be one printable selector no longer than (.+?) bytes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/task_spec.rs","lineNumber":256,"sourceCode":"        worker.agent_profile.as_deref(),\n    )?;\n    validate_worker_token(task_id, \"worker.loadout\", worker.loadout.as_deref())?;\n    validate_worker_token(task_id, \"worker.model_class\", worker.model_class.as_deref())?;\n    validate_worker_model(task_id, worker.model.as_deref())?;\n    Ok(())\n}\n\nfn validate_worker_selector(task_id: &str, field: &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} {field} cannot be empty\");\n    }\n    if trimmed != value || value.len() > MAX_FLEET_NAME_BYTES || value.chars().any(char::is_control)\n    {\n        bail!(\n            \"fleet task {task_id} {field} must be one printable selector no longer than {MAX_FLEET_NAME_BYTES} bytes\"\n        );\n    }\n    Ok(())\n}\n\nfn validate_worker_token(task_id: &str, field: &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} {field} cannot be empty\");\n    }\n    if trimmed != value || !trimmed.chars().all(is_worker_token_char) {\n        bail!(\n            \"fleet task {task_id} {field} must be a simple token, not a path or provider/model id\"\n        );","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/fleet/task_spec.rs#L238-L274","documentation":"Worker selectors, when present, must be one printable line no longer than MAX_FLEET_NAME_BYTES with no leading/trailing whitespace. validate_worker_selector rejects values that were trimmed differently from the original, exceed the byte cap, or contain control characters. Selectors must be stable, canonical strings.","triggerScenarios":"validate_worker_profile sees a selector containing surrounding whitespace (trimmed != value), a value over MAX_FLEET_NAME_BYTES, or control characters.","commonSituations":"Copy-pasting a selector with a trailing space or newline; multi-line label expressions; overly long selector strings.","solutions":["Trim the selector before storing it (only untrimmed values pass)","Remove control characters/newlines from the selector","Shorten the selector to at most MAX_FLEET_NAME_BYTES bytes"],"exampleFix":"// before\nselector: Some(\" gpu=true \")\n// after\nselector: Some(\"gpu=true\")","handlingStrategy":"validation","validationCode":"fn selector_format_ok(v: &str) -> bool { v.trim() == v && v.len() <= MAX_FLEET_NAME_BYTES && !v.chars().any(char::is_control) }","typeGuard":"fn canonical_selector(v: &str) -> Option<&str> { selector_format_ok(v).then_some(v) }","tryCatchPattern":"if let Err(e) = validate_worker_selector(task_id, \"selector\", value) { if e.to_string().contains(\"printable selector\") { eprintln!(\"trim/control-char issue: {e}\"); } }","preventionTips":["Trim selectors at every write site","Keep selectors as canonical label expressions","Bound selector length when accepting free-form input"],"tags":["validation","format","fleet"],"backgroundTag":"invalid-argument-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"}