{"record":{"id":"dee12591db5361b9","repo":"jdx/mise","slug":"invalid-task-action-identity","errorCode":null,"errorMessage":"invalid task action identity","messagePattern":"invalid task action identity","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mise-cache-core/src/agent.rs","lineNumber":1797,"sourceCode":"            let response = match serde_json::from_str(&line) {\n                Ok(request) => self.respond(request).await,\n                Err(error) => AgentResponse::Error {\n                    message: format!(\"invalid agent request: {error}\"),\n                },\n            };\n            send_response(&mut writer, &response).await?;\n        }\n        Ok(())\n    }\n}\n\nfn validate_task_identity(task: &str) -> Result<()> {\n    if task.len() != 64\n        || !task\n            .bytes()\n            .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))\n    {\n        bail!(\"invalid task action identity\");\n    }\n    Ok(())\n}\n\nfn validate_action_prediction(prediction: &ActionPrediction) -> Result<()> {\n    prediction.invocation.validate()?;\n    prediction.action.validate()?;\n    if prediction.adapter.is_empty()\n        || !prediction\n            .adapter\n            .bytes()\n            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_'))\n    {\n        bail!(\"invalid action prediction adapter\");\n    }\n    if prediction.payload.len() > MAX_ACTION_PREDICTION_PAYLOAD {\n        bail!(\"action prediction payload is too large\");\n    }","sourceCodeStart":1779,"sourceCodeEnd":1815,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/crates/mise-cache-core/src/agent.rs#L1779-L1815","documentation":"validate_task_identity requires task ids to be exactly 64 ASCII lowercase hex characters (b'0'..=b'9', b'a'..=b'f') — the blake3 digest format used as cache key throughout the agent. Wrong length, uppercase hex, non-hex bytes, or an empty string all fail, in both begin_task/commit paths and prediction recording.","triggerScenarios":"Passing a human-readable task name, a 40-char sha1, a 64-char UPPERCASE digest, a digest with 'g'-'z' characters, or confusing the begin_task run token with the task identity.","commonSituations":"Clients deriving ids with a different hash (sha1/sha256 hex uppercase); feeding filenames or task labels where the digest belongs; manual testing with placeholder strings.","solutions":["Compute task ids as 64-char lowercase hex digests (e.g. blake3 of the task identity)","Lowercase the id before sending: id.to_ascii_lowercase()","Do not pass the run token from begin_task where a task identity is expected — they are different values"],"exampleFix":"// before\nlet task = \"my-task-name\";\n// after\nlet task = CacheDigest::blake3(task_identity_bytes).hash; // 64 lowercase hex chars","handlingStrategy":"validation","validationCode":"let task = task.trim().to_ascii_lowercase();\nassert!(is_task_identity(&task), \"task id must be 64 lowercase hex chars\");\nlet run = agent.begin_task(&task).await?;","typeGuard":"fn is_task_identity(task: &str) -> bool {\n    task.len() == 64\n        && task.bytes().all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))\n}","tryCatchPattern":null,"preventionTips":["Derive task ids from a 256-bit hash and hex-encode lowercase (blake3 preferred, matches the agent)","Keep task identity and the begin_task run token as distinct, non-interchangeable values","Add the 64-lowercase-hex assertion at client boundaries to fail fast"],"tags":["mise-cache","validation","identifier","hash"],"backgroundTag":"invalid-identifier-format","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}