zeroclaw-labs/zeroclaw · error
Encrypted value too short (missing nonce)
Error message
Encrypted value too short (missing nonce)
What it means
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.
Source
Thrown at crates/zeroclaw-config/src/secrets.rs:330
} else if is_onepassword_ref(value) {
let plaintext = resolve_onepassword_ref(value)?;
Ok((plaintext, None))
} else {
// Plaintext — no migration needed
Ok((value.to_string(), None))
}
}
/// Check if a value uses the legacy `enc:` format that should be migrated.
pub fn needs_migration(value: &str) -> bool {
value.starts_with("enc:")
}
/// Decrypt using ChaCha20-Poly1305 (current secure format).
fn decrypt_chacha20(&self, hex_str: &str) -> Result<String> {
let blob =
hex_decode(hex_str).context("Failed to decode encrypted secret (corrupt hex)")?;
anyhow::ensure!(
blob.len() > NONCE_LEN,
"Encrypted value too short (missing nonce)"
);
let (nonce_bytes, ciphertext) = blob.split_at(NONCE_LEN);
let nonce = Nonce::from_slice(nonce_bytes);
self.get_key(|key| {
let key = Key::from_slice(key);
let cipher = ChaCha20Poly1305::new(key);
let plaintext_bytes = cipher.decrypt(nonce, ciphertext).map_err(|e| {
let backend = self.key_source.backend_name();
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({View on GitHub (pinned to 88bb9c8533)
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
Example fix
# before: value truncated during copy (only 8 bytes after decode) # after: re-store the secret to regenerate a full encrypted blob zeroclaw config set-secret api_key # then paste the plaintext when prompted
Defensive patterns
Strategy: validation
Validate before calling
fn looks_like_chacha20_ciphertext(v: &str) -> bool {
v.len() % 2 == 0
&& v.chars().all(|c| c.is_ascii_hexdigit())
&& v.len() / 2 > 12 // > NONCE_LEN (12): nonce + at least 1 byte of ciphertext/tag
}
if !looks_like_chacha20_ciphertext(&stored_value) {
// re-store the secret instead of attempting decrypt
} Try / catch
catch the decrypt Result; on message "Encrypted value too short (missing nonce)" re-store the secret via the secrets CLI rather than retrying decrypt
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Key file must contain exactly 32 bytes (got {})
- matrix: configure either `access_token` or `password`
- Nextcloud Talk: no bot secret configured (set bot_token or w
- model_provider `{family}` has multiple configured aliases; u
- microsoft365.client_secret must not be empty when auth_flow
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/9a1ab3b412b2f71c.
Report an issue: GitHub.