jdx/mise · error
data too short to contain nonce
Error message
data too short to contain nonce
What it means
decrypt_data expects encrypted env-cache blobs in the format [12-byte nonce || ciphertext+tag] under AES-GCM with a 32-byte key. If the data is shorter than 12 bytes it cannot even contain a nonce, so decryption aborts — this guards against decrypting truncated or unencrypted data.
Source
Thrown at src/toolset/env_cache.rs:43
}
fn encrypt_data(data: &[u8], key: &[u8; 32]) -> Result<Vec<u8>> {
let cipher = ChaCha20Poly1305::new_from_slice(key)
.map_err(|e| eyre::eyre!("failed to create cipher: {}", e))?;
let nonce = Nonce::generate();
let ciphertext = cipher
.encrypt(&nonce, data)
.map_err(|e| eyre::eyre!("encryption failed: {}", e))?;
// Format: nonce || ciphertext
let mut result = nonce.to_vec();
result.extend(ciphertext);
Ok(result)
}
fn decrypt_data(data: &[u8], key: &[u8; 32]) -> Result<Vec<u8>> {
if data.len() < 12 {
bail!("data too short to contain nonce");
}
let nonce =
Nonce::try_from(&data[..12]).map_err(|e| eyre::eyre!("failed to read nonce: {}", e))?;
let ciphertext = &data[12..];
let cipher = ChaCha20Poly1305::new_from_slice(key)
.map_err(|e| eyre::eyre!("failed to create cipher: {}", e))?;
let plaintext = cipher
.decrypt(&nonce, ciphertext)
.map_err(|e| eyre::eyre!("decryption failed: {}", e))?;
Ok(plaintext)
}
fn validate_watch_files(watch_files: &[PathBuf], expected_mtimes: &[u64]) -> Result<()> {
if watch_files.len() != expected_mtimes.len() {
bail!("watch file count mismatch");View on GitHub (pinned to afd2eddd3a)
Solutions
- Delete the corrupted env cache file so it is regenerated on the next load
- Clear the mise cache directory (e.g. `mise cache clean` or remove the env cache location) if multiple entries are corrupt
- Check for disk-full/IO issues that truncated writes; ensure the same mise version rewrites the cache
Example fix
// before rm $(mise cache dir)/env-cache.bin # truncated file // after: next `mise env` load rewrites a valid nonce+ciphertext cache
Defensive patterns
Strategy: try-catch
Validate before calling
// verify cache blob is plausibly encrypted before load const buf = fs.readFileSync(cachePath); if (buf.length < 12 + 16) fs.rmSync(cachePath); // too short for nonce+tag; let it regenerate
Type guard
function isEncryptedBlob(b) { return Buffer.isBuffer(b) && b.length >= 28; } // 12 nonce + 16 GCM tag Try / catch
// delete and rebuild cache on decrypt failure
match env_cache::load(path) {
Err(e) if e.to_string().contains("data too short") => {
std::fs::remove_file(path).ok();
env_cache::load(path).or_default()
}
r => r,
} Prevention
- Guard cache writes against truncation (write to temp then rename)
- Clear caches after switching mise versions or encryption settings
- Treat cache decryption failure as cache-miss, not fatal, in wrappers
When it happens
Trigger: Toolset env_cache load (or the encryption roundtrip test) reads a cache file whose bytes are < 12 long — a truncated/corrupted cache file, an empty file, or a file written by an incompatible/unencrypted format.
Common situations: Disk-full or crash mid-write leaving a truncated cache; a cache produced by a different mise version or encryption setting; manually copying/clearing cache files.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- action prediction payload is too large
- task action manifest has an invalid identity
- task action manifest contains duplicate predictions
- remote action manifest keys must use blake3
- remote action manifest ETag does not match its body
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/92d569f98d2f73e8.
Report an issue: GitHub.