{"record":{"id":"4452eb9da741ac00","repo":"Hmbown/CodeWhale","slug":"invalid-preallocated-task-id-expected-task-16hex","errorCode":null,"errorMessage":"Invalid preallocated task id: expected task_<16hex>","messagePattern":"Invalid preallocated task id: expected task_<16hex>","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/task_manager.rs","lineNumber":3084,"sourceCode":"            &self.queue_path,\n            &QueueFile {\n                queue: queue.iter().cloned().collect(),\n            },\n        )\n    }\n\n    fn persist_task_locked(&self, task: &TaskRecord) -> Result<()> {\n        let path = self.tasks_dir.join(format!(\"{}.json\", task.id));\n        write_json_atomic(&path, task)\n    }\n}\n\nfn validate_preallocated_task_id(task_id: &str) -> Result<()> {\n    if task_id.len() != 21\n        || !task_id.starts_with(\"task_\")\n        || !task_id[5..].chars().all(|ch| ch.is_ascii_hexdigit())\n    {\n        bail!(\"Invalid preallocated task id: expected task_<16hex>\");\n    }\n    Ok(())\n}\n\nfn read_bound_task_file(path: &Path, task_id: &str) -> Result<Option<TaskRecord>> {\n    let bytes = match fs::read(path) {\n        Ok(bytes) => bytes,\n        Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None),\n        Err(error) => return Err(error).context(\"read bound task\"),\n    };\n    let task: TaskRecord = serde_json::from_slice(&bytes).context(\"decode bound task\")?;\n    if task.id != task_id || task.schema_version > CURRENT_TASK_SCHEMA_VERSION {\n        bail!(\"Bound task identity or schema does not match its durable admission\");\n    }\n    Ok(Some(task))\n}\n\npub(crate) fn validate_bound_task_request(","sourceCodeStart":3066,"sourceCodeEnd":3102,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/task_manager.rs#L3066-L3102","documentation":"Client-preallocated task ids must be exactly `task_` followed by 16 ASCII hex digits (21 chars total). This validator rejects any other shape before the id is used in file paths or admission, preventing malformed or unsafe ids from entering the store.","triggerScenarios":"Calling task creation/admission with a client-supplied preallocated id that is not 21 chars, does not start with `task_`, or contains non-hex characters after the prefix.","commonSituations":"Generating ids with the wrong length (uuid strings, 8- or 12-char hex); forgetting the `task_` prefix; uppercase vs lowercase or stray whitespace; using a timestamp or numeric id instead of hex.","solutions":["Generate the id as `task_` + 16 lowercase hex chars (e.g. from 8 random bytes)","Trim/normalize the id and re-validate with the same rule before submitting","Prefer letting the manager allocate the id instead of preallocating one"],"exampleFix":"// before\nlet id = format!(\"{}\", uuid::Uuid::new_v4()); // wrong shape\n// after\nlet id = format!(\"task_{}\", hex::encode(rand::random::<[u8; 8]>())); // task_ + 16 hex","handlingStrategy":"validation","validationCode":"fn valid_preallocated_id(id: &str) -> bool {\n    id.len() == 21 && id.starts_with(\"task_\") && id[5..].bytes().all(|b| b.is_ascii_hexdigit())\n}","typeGuard":"fn as_task_id(s: &str) -> Option<&str> {\n    (s.len() == 21 && s.starts_with(\"task_\") && s[5..].bytes().all(|b| b.is_ascii_hexdigit())).then_some(s)\n}","tryCatchPattern":"match manager.create_task_with_preallocated_id(&id, req).await {\n    Err(e) if e.to_string().contains(\"Invalid preallocated task id\") => {\n        let id = format!(\"task_{}\", hex::encode(rand::random::<[u8; 8]>()));\n        manager.create_task_with_preallocated_id(&id, req).await?;\n    }\n    other => other?,\n}","preventionTips":["Generate ids from a single shared helper that always emits task_<16hex>","Validate ids at the client boundary before sending","Never build ids from uuids, timestamps, or unprefixed hex"],"tags":["validation","identifier","format","task-manager"],"backgroundTag":"invalid-identifier-format","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"}