{"record":{"id":"52136fa4e88eac4c","repo":"jdx/mise","slug":"invalid-remote-task-cache-key","errorCode":null,"errorMessage":"invalid remote task cache key","messagePattern":"invalid remote task cache key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/task_cache_store.rs","lineNumber":840,"sourceCode":"            }\n            RestoredNode::Symlink { target, .. } => {\n                header.set_size(0);\n                archive.append_link(&mut header, path, target)?;\n            }\n        }\n    }\n    let encoder = archive.into_inner()?;\n    encoder.finish()?;\n    Ok(archive_file)\n}\n\nfn validate_remote_key(key: &str) -> Result<()> {\n    if key.len() != 64\n        || !key\n            .bytes()\n            .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))\n    {\n        bail!(\"invalid remote task cache key\");\n    }\n    Ok(())\n}\n\npub(crate) struct LocalTaskCacheStore {\n    root: PathBuf,\n}\n\nimpl LocalTaskCacheStore {\n    pub(crate) fn new(root: PathBuf) -> Self {\n        Self { root }\n    }\n\n    fn paths(&self, key: &str) -> (PathBuf, PathBuf) {\n        (\n            self.root.join(format!(\"{key}.tar.zst\")),\n            self.root.join(format!(\"{key}.json\")),\n        )","sourceCodeStart":822,"sourceCodeEnd":858,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/task/task_cache_store.rs#L822-L858","documentation":"validate_remote_key requires a remote task cache key to be exactly 64 characters of lowercase hex (a sha256-style digest). Any key that differs in length or contains characters outside [0-9a-f] is rejected, since keys are content digests by construction.","triggerScenarios":"Calling the remote cache store (commit/get) with a key string that is not exactly 64 lowercase hex characters — e.g. an uppercase hash, a truncated hash, a prefixed key like \"sha256:...\", or a human-readable cache name.","commonSituations":"Custom cache-server integrations that generate their own key format; configuration pointing cache operations at user-supplied identifiers instead of computed digests; keys copied with surrounding whitespace or wrong casing.","solutions":["Compute the key as the lowercase hex sha256 digest of the cache inputs, and pass that exact string.","Normalize the key before use: lowercase it and strip prefixes/whitespace.","Check for truncation — a 32-char key is a half-written md5-style digest, not the required 64-char sha256 hex.","If a custom producer writes keys, switch it to the same 64-hex digest scheme mise uses."],"exampleFix":"// before\nlet key = format!(\"sha256:{:x}\", digest); // prefixed, wrong format\n// after\nlet key = hex::encode(Sha256::digest(inputs)); // 64 lowercase hex chars","handlingStrategy":"validation","validationCode":"const isValidKey = k => /^[0-9a-f]{64}$/.test(k);\nif (!isValidKey(key)) throw new Error('key must be 64 lowercase hex chars');","typeGuard":"const isHex64 = (k) => typeof k === 'string' && /^[0-9a-f]{64}$/.test(k);","tryCatchPattern":null,"preventionTips":["Always derive keys as lowercase hex sha256 of inputs.","Lowercase and strip prefixes/whitespace before passing keys.","Never pass human-readable names as cache keys."],"tags":["task-cache","remote-cache","cache-key","validation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}