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

  1. Delete the corrupted env cache file so it is regenerated on the next load
  2. Clear the mise cache directory (e.g. `mise cache clean` or remove the env cache location) if multiple entries are corrupt
  3. 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

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


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/92d569f98d2f73e8. Report an issue: GitHub.