Hmbown/CodeWhale · error

Task prompt cannot be empty

Error message

Task prompt cannot be empty

What it means

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.

Solutions

  1. Provide a non-empty prompt in NewTaskRequest before admission
  2. Trim the prompt in the caller and reject empty input at the UI/CLI layer with a friendlier message
  3. For templated prompts, validate that placeholder substitution produced non-empty text
  4. If a prompt is genuinely optional for this flow, use the API variant designed for prompt-less tasks, not add_task_with_id

Example fix

// before
let req = NewTaskRequest { prompt: user_input.clone(), .. };
mgr.add_task_with_id(req, id).await?;
// after
let prompt = user_input.trim();
anyhow::ensure!(!prompt.is_empty(), "prompt is required");
let req = NewTaskRequest { prompt: prompt.to_string(), .. };
mgr.add_task_with_id(req, id).await?;
Defensive patterns

Strategy: validation

Validate before calling

anyhow::ensure!(!req.prompt.trim().is_empty(), "task prompt is required");

Prevention

When it happens

Trigger: Calling add_task_with_id (or the recovery path that validates the same request) with NewTaskRequest { prompt: "" } or a prompt consisting only of whitespace.

Common situations: 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.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/931162fefcf94cf8. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/task_manager.rs:1679

                    validate_bound_task_request(&task, &request)?;
                    Ok(task)
                } else {
                    Err(error)
                }
            }
        }
    }

    /// 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 (req.model_provider.is_some() || req.model_provider_id.is_some())
            && req
                .model
                .as_deref()
                .is_none_or(|model| model.trim().is_empty())
        {
            bail!("A pinned task provider requires an explicit model");
        }
        // The worker runs this same projection when it opens the task's
        // thread. Running it here as well refuses an unknown mode or posture
        // at the boundary the request crossed, instead of after the task has
        // sat in the durable queue and a worker has claimed it.
        crate::runtime_policy::RuntimePolicyProjection::from_request(
            req.mode
                .as_deref()
                .filter(|mode| !mode.trim().is_empty())
                .unwrap_or(&self.cfg.default_mode),

View on GitHub (pinned to 73e0f67d83)