Hmbown/CodeWhale · error · anyhow::Error
Task prompt cannot be empty
Error message
Task prompt cannot be empty
What it means
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.
Source
Thrown at crates/tui/src/task_manager.rs:1231
}
/// Allocate the durable owner identity before queue insertion so callers
/// can register graph spawn intent first.
#[must_use]
pub(crate) fn new_task_id() -> String {
format!("task_{}", &Uuid::new_v4().simple().to_string()[..16])
}
/// 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 task_id.len() != 21
|| !task_id.starts_with("task_")
|| !task_id[5..].chars().all(|ch| ch.is_ascii_hexdigit())
{
bail!("Invalid preallocated task id: expected task_<16hex>");
}
let task = TaskRecord {
schema_version: CURRENT_TASK_SCHEMA_VERSION,
// 16 random hex chars (was 8; ~60 bits of entropy once UUIDv4's
// fixed version nibble is discounted): task ids live in durable
// state that accumulates across restarts, and a collision
// overwrites a record while leaving a duplicate queue entry.
// `resolve_task_id` matches by prefix, so short references still
// work.
id: task_id,
prompt,View on GitHub (pinned to 0c42157ee5)
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.
Example fix
// before
let task = tm.add_task_with_id(NewTaskRequest { prompt: prompt_from_user.clone(), .. }, id).await?;
// after
let prompt = prompt_from_user.trim();
if prompt.is_empty() {
return Err(anyhow!("prompt required to create a task"));
}
let task = tm.add_task_with_id(NewTaskRequest { prompt: prompt.to_string(), .. }, id).await?; Defensive patterns
Strategy: validation
Validate before calling
fn has_prompt(req: &NewTaskRequest) -> bool {
!req.prompt.trim().is_empty()
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Automation or agent pipelines that build NewTaskRequest from optional template variables; trimming input upstream and passing the trimmed-empty string; tests with placeholder prompts.
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
- Invalid preallocated task id: expected task_<16hex>
- unsupported hunt_verdict task update '{other}'. Expected one
- context_window must be greater than 0
- custom provider '{provider_id}' must set [providers.{provide
- unknown field '{field_key}' for built-in provider '{provider
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/931162fefcf94cf8.
Report an issue: GitHub.