Hmbown/CodeWhale · error · anyhow::Error

Invalid preallocated task id: expected task_<16hex>

Error message

Invalid preallocated task id: expected task_<16hex>

What it means

add_task_with_id validates the caller-supplied preallocated id: it must be exactly 21 chars, start with 'task_', and the remaining 16 characters must be ASCII hex digits. The 16-hex format (about 60 bits of entropy) replaced an older 8-hex format because task records accumulate across restarts and a collision would overwrite a record while leaving a duplicate queue entry.

Source

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

        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,
            model: req.model.unwrap_or_else(|| self.cfg.default_model.clone()),
            workspace: match req.workspace {
                Some(workspace) => workspace,
                None => self.default_workspace().await,
            },
            mode: req.mode.unwrap_or_else(|| self.cfg.default_mode.clone()),

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Generate ids exactly the way the task manager does: format!("task_{}", &Uuid::new_v4().simple().to_string()[..16]).
  2. If you hold a persistent id generator, enforce len==21, prefix 'task_', and [0-9a-f] over the last 16 chars before calling.
  3. Regenerate rather than repair malformed ids at runtime; never widen the parser to accept the legacy 8-hex form.

Example fix

// before
let id = format!("task_{:08x", rand::random::<u32>()); // 8 hex, wrong length
let task = tm.add_task_with_id(req, id).await?;

// after
let id = format!("task_{}", &Uuid::new_v4().simple().to_string()[..16]);
let task = tm.add_task_with_id(req, id).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_task_id(id: &str) -> bool {
    id.len() == 21
        && id.starts_with("task_")
        && id[5..].chars().all(|ch| ch.is_ascii_hexdigit())
}

fn new_task_id() -> String {
    format!("task_{}", &Uuid::new_v4().simple().to_string()[..16])
}

Type guard

fn is_task_id(id: &str) -> bool {
    id.len() == 21 && id.starts_with("task_") && id[5..].bytes().all(|b| b.is_ascii_hexdigit())
}

Prevention

When it happens

Trigger: Passing an id generated by old code that produced task_ + 8 hex chars; passing a UUID, an arbitrary string, uppercase hex, or a wrong-length id to add_task_with_id.

Common situations: Upgrading a codebase that generated task_<8hex> ids before this format change; mixing hand-written id generators with the task manager; copy-pasting ids from logs that were truncated.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/4452eb9da741ac00. Report an issue: GitHub.