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
- Generate ids exactly the way the task manager does: format!("task_{}", &Uuid::new_v4().simple().to_string()[..16]).
- If you hold a persistent id generator, enforce len==21, prefix 'task_', and [0-9a-f] over the last 16 chars before calling.
- 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
- Always mint ids with the same generator as the task manager (task_ + 16 lowercase hex).
- Never persist externally-generated free-form ids; validate them at the boundary.
- Watch for the legacy 8-hex format after upgrades and regenerate instead of padding.
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
- {label} cannot be empty
- {label} cannot contain leading or trailing whitespace
- {label} contains unsupported characters
- Task prompt cannot be empty
- unsupported hunt_verdict task update '{other}'. Expected one
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/4452eb9da741ac00.
Report an issue: GitHub.