{"record":{"id":"9a1ab3b412b2f71c","repo":"zeroclaw-labs/zeroclaw","slug":"encrypted-value-too-short-missing-nonce","errorCode":null,"errorMessage":"Encrypted value too short (missing nonce)","messagePattern":"Encrypted value too short \\(missing nonce\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/secrets.rs","lineNumber":330,"sourceCode":"        } else if is_onepassword_ref(value) {\n            let plaintext = resolve_onepassword_ref(value)?;\n            Ok((plaintext, None))\n        } else {\n            // Plaintext — no migration needed\n            Ok((value.to_string(), None))\n        }\n    }\n\n    /// Check if a value uses the legacy `enc:` format that should be migrated.\n    pub fn needs_migration(value: &str) -> bool {\n        value.starts_with(\"enc:\")\n    }\n\n    /// Decrypt using ChaCha20-Poly1305 (current secure format).\n    fn decrypt_chacha20(&self, hex_str: &str) -> Result<String> {\n        let blob =\n            hex_decode(hex_str).context(\"Failed to decode encrypted secret (corrupt hex)\")?;\n        anyhow::ensure!(\n            blob.len() > NONCE_LEN,\n            \"Encrypted value too short (missing nonce)\"\n        );\n\n        let (nonce_bytes, ciphertext) = blob.split_at(NONCE_LEN);\n        let nonce = Nonce::from_slice(nonce_bytes);\n\n        self.get_key(|key| {\n            let key = Key::from_slice(key);\n            let cipher = ChaCha20Poly1305::new(key);\n\n            let plaintext_bytes = cipher.decrypt(nonce, ciphertext).map_err(|e| {\n                let backend = self.key_source.backend_name();\n                ::zeroclaw_log::record!(\n                    ERROR,\n                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)\n                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                        .with_attrs(::serde_json::json!({","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/secrets.rs#L312-L348","documentation":"decrypt_chacha20 hex-decodes the stored secret and requires strictly more than NONCE_LEN (12) bytes: a 12-byte ChaCha20-Poly1305 nonce plus at least some ciphertext/tag material. A value of 12 bytes or fewer cannot contain a nonce, so it is rejected as corrupt or truncated before any cryptographic operation.","triggerScenarios":"A truncated encrypted value (partial copy-paste into the config); manual edits of the secrets file; a plaintext or legacy-format value being fed into the ChaCha20 decrypt path; pointing decryption at the wrong field or file.","commonSituations":"Operators copying encrypted blobs by hand and losing characters; config files mangled by templating or line wrapping; mixing key files so an old-format value is read as ChaCha20; secrets values damaged in transit between environments.","solutions":["Re-store the secret through the secrets CLI so it is freshly encrypted in the current format","Verify the stored value is valid even-length hex and decodes to more than 12 bytes","Confirm you are reading the same config/secrets file and key that produced the value"],"exampleFix":"# before: value truncated during copy (only 8 bytes after decode)\n# after: re-store the secret to regenerate a full encrypted blob\nzeroclaw config set-secret api_key   # then paste the plaintext when prompted","handlingStrategy":"validation","validationCode":"fn looks_like_chacha20_ciphertext(v: &str) -> bool {\n    v.len() % 2 == 0\n        && v.chars().all(|c| c.is_ascii_hexdigit())\n        && v.len() / 2 > 12 // > NONCE_LEN (12): nonce + at least 1 byte of ciphertext/tag\n}\n\nif !looks_like_chacha20_ciphertext(&stored_value) {\n    // re-store the secret instead of attempting decrypt\n}","typeGuard":null,"tryCatchPattern":"catch the decrypt Result; on message \"Encrypted value too short (missing nonce)\" re-store the secret via the secrets CLI rather than retrying decrypt","preventionTips":["Always create/update secrets through the secrets CLI, never by editing encrypted blobs by hand","Add length/hex sanity checks in tooling that syncs config between environments","Keep key file and secrets file paired (same environment) so values are never decrypted under the wrong format expectations"],"tags":["crypto","secrets","chacha20","corrupt-data","config","rust"],"backgroundTag":"corrupt-encrypted-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}