{"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":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/task_manager.rs","lineNumber":1679,"sourceCode":"                    validate_bound_task_request(&task, &request)?;\n                    Ok(task)\n                } else {\n                    Err(error)\n                }\n            }\n        }\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 (req.model_provider.is_some() || req.model_provider_id.is_some())\n            && req\n                .model\n                .as_deref()\n                .is_none_or(|model| model.trim().is_empty())\n        {\n            bail!(\"A pinned task provider requires an explicit model\");\n        }\n        // The worker runs this same projection when it opens the task's\n        // thread. Running it here as well refuses an unknown mode or posture\n        // at the boundary the request crossed, instead of after the task has\n        // sat in the durable queue and a worker has claimed it.\n        crate::runtime_policy::RuntimePolicyProjection::from_request(\n            req.mode\n                .as_deref()\n                .filter(|mode| !mode.trim().is_empty())\n                .unwrap_or(&self.cfg.default_mode),","sourceCodeStart":1661,"sourceCodeEnd":1697,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/task_manager.rs#L1661-L1697","documentation":"add_task_with_id validates NewTaskRequest at the durable-admission boundary: the prompt is trimmed and must be non-empty. An empty or whitespace-only prompt cannot produce a runnable task, so admission is refused before the record is written to the queue.","triggerScenarios":"Calling add_task_with_id (or the recovery path that validates the same request) with NewTaskRequest { prompt: \"\" } or a prompt consisting only of whitespace.","commonSituations":"A UI form submitted without text; a template/automation rule whose prompt placeholder resolved to nothing; trimming logic upstream removed the whole string; copying a request struct with a default empty prompt.","solutions":["Provide a non-empty prompt in NewTaskRequest before admission","Trim the prompt in the caller and reject empty input at the UI/CLI layer with a friendlier message","For templated prompts, validate that placeholder substitution produced non-empty text","If a prompt is genuinely optional for this flow, use the API variant designed for prompt-less tasks, not add_task_with_id"],"exampleFix":"// before\nlet req = NewTaskRequest { prompt: user_input.clone(), .. };\nmgr.add_task_with_id(req, id).await?;\n// after\nlet prompt = user_input.trim();\nanyhow::ensure!(!prompt.is_empty(), \"prompt is required\");\nlet req = NewTaskRequest { prompt: prompt.to_string(), .. };\nmgr.add_task_with_id(req, id).await?;","handlingStrategy":"validation","validationCode":"anyhow::ensure!(!req.prompt.trim().is_empty(), \"task prompt is required\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate prompts at the UI/CLI entry point before building NewTaskRequest","Guard templated prompts against empty substitution results","Never construct requests from default/placeholder structs"],"tags":["rust","validation","tasks","empty-input"],"backgroundTag":"empty-required-field","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"}