{"record":{"id":"931162fefcf94cf8","repo":"Hmbown/CodeWhale","slug":"task-prompt-cannot-be-empty","errorCode":null,"errorMessage":"Task prompt cannot be empty","messagePattern":"Task prompt cannot be empty","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/task_manager.rs","lineNumber":1231,"sourceCode":"    }\n\n    /// Allocate the durable owner identity before queue insertion so callers\n    /// can register graph spawn intent first.\n    #[must_use]\n    pub(crate) fn new_task_id() -> String {\n        format!(\"task_{}\", &Uuid::new_v4().simple().to_string()[..16])\n    }\n\n    /// Enqueue using a preallocated id. This is crate-visible only for the\n    /// model tool's register-before-work transaction.\n    pub(crate) async fn add_task_with_id(\n        &self,\n        req: NewTaskRequest,\n        task_id: String,\n    ) -> Result<TaskRecord> {\n        let prompt = req.prompt.trim().to_string();\n        if prompt.is_empty() {\n            bail!(\"Task prompt cannot be empty\");\n        }\n        if task_id.len() != 21\n            || !task_id.starts_with(\"task_\")\n            || !task_id[5..].chars().all(|ch| ch.is_ascii_hexdigit())\n        {\n            bail!(\"Invalid preallocated task id: expected task_<16hex>\");\n        }\n\n        let task = TaskRecord {\n            schema_version: CURRENT_TASK_SCHEMA_VERSION,\n            // 16 random hex chars (was 8; ~60 bits of entropy once UUIDv4's\n            // fixed version nibble is discounted): task ids live in durable\n            // state that accumulates across restarts, and a collision\n            // overwrites a record while leaving a duplicate queue entry.\n            // `resolve_task_id` matches by prefix, so short references still\n            // work.\n            id: task_id,\n            prompt,","sourceCodeStart":1213,"sourceCodeEnd":1249,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/task_manager.rs#L1213-L1249","documentation":"add_task_with_id rejects a NewTaskRequest whose prompt is empty after trimming. Tasks are meaningless without an instruction, so enqueue fails fast before any id is staged, queued, or persisted. The check applies to both the normal enqueue path and the model tool's register-before-work transaction that preallocates an id.","triggerScenarios":"Calling add_task_with_id (or the model task tool that fronts it) with a prompt of \"\", whitespace, or a value that only contains newlines/tabs; programmatic callers forwarding user input that was never validated.","commonSituations":"Automation or agent pipelines that build NewTaskRequest from optional template variables; trimming input upstream and passing the trimmed-empty string; tests with placeholder prompts.","solutions":["Validate and reject empty prompts at the call site before constructing NewTaskRequest.","If the prompt comes from user or LLM input, require a non-blank default or re-prompt instead of enqueueing.","Check req.prompt.trim() explicitly, not just is_empty(), because whitespace-only prompts are also rejected."],"exampleFix":"// before\nlet task = tm.add_task_with_id(NewTaskRequest { prompt: prompt_from_user.clone(), .. }, id).await?;\n\n// after\nlet prompt = prompt_from_user.trim();\nif prompt.is_empty() {\n    return Err(anyhow!(\"prompt required to create a task\"));\n}\nlet task = tm.add_task_with_id(NewTaskRequest { prompt: prompt.to_string(), .. }, id).await?;","handlingStrategy":"validation","validationCode":"fn has_prompt(req: &NewTaskRequest) -> bool {\n    !req.prompt.trim().is_empty()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Trim user/LLM input at the boundary and reject blank prompts there.","Distinguish 'no task requested' from 'task with empty prompt' in your control flow.","Cover this in API tests: whitespace-only prompts must fail before any id is consumed."],"tags":["task","validation","prompt","rust"],"backgroundTag":"missing-required-argument","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}