jdx/mise · error

encrypted file does not match its path or mode: {path}

Error message

encrypted file does not match its path or mode: {path}

What it means

This error comes from the integrity validation of an encrypted-file envelope in mise's history sync. The decrypted inner plaintext must exactly match the outer envelope's path, mode, and scheme, use a safe branch path, and use a supported git mode; any mismatch means the envelope was tampered with, corrupted, or crafted inconsistently. It is thrown by validate() before decrypt() will produce file contents.

Source

Thrown at src/system/history/sync/files.rs:241

    // Only encrypted envelopes have this limit; do not change plaintext sync.
    let bytes = repo.cat_object_bounded(&object.1, limit)?;
    let Some(body) = bytes.strip_prefix(MAGIC) else {
        return Ok(None);
    };
    Ok(Some(
        rmp_serde::from_slice(body).wrap_err("invalid encrypted file envelope")?,
    ))
}

fn validate(path: &str, outer: &Envelope, inner: &Plaintext) -> Result<()> {
    if outer.path != path
        || inner.path != path
        || inner.mode != outer.mode
        || inner.scheme != outer.scheme
        || !layout::is_safe_branch_path(path)
        || !matches!(inner.mode.as_str(), "100644" | "100755" | "120000")
    {
        bail!("encrypted file does not match its path or mode: {path}");
    }
    Ok(())
}

pub(crate) fn decrypt(
    repo: &HistoryRepo,
    path: &str,
    object: &Object,
    interactive: bool,
) -> Result<Object> {
    let outer = envelope(repo, object, agecrypt::MAX_ENCRYPTED_BYTES)?
        .ok_or_else(|| eyre::eyre!("missing encrypted file envelope: {path}"))?;
    if control_file(path) {
        bail!("setup configuration itself cannot be encrypted: {path}");
    }
    if outer.path != path {
        bail!("encrypted file does not match its path: {path}");
    }

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Re-pull the encrypted store from origin (mise bootstrap dotfiles pull) to replace the corrupt envelope.
  2. Re-encrypt the file from its plaintext source so path/mode/scheme match consistently.
  3. Check the file's path is a safe branch path and its mode is a supported git mode (100644/100755/120000).
  4. If a merge caused the mismatch, resolve the encrypted file by taking one whole side, never hand-merging envelope bytes.

Example fix

// before: hand-merged envelope with mismatched inner path
$ git checkout --theirs .config/secrets.env.enc
// after: replace the whole envelope from a verified side
$ git checkout origin/history -- .config/secrets.env.enc
$ mise bootstrap dotfiles pull
Defensive patterns

Strategy: validation

Validate before calling

fn safe_to_decrypt(path: &str, mode: &str) -> bool {
    layout::is_safe_branch_path(path)
        && matches!(mode, "100644" | "100755" | "120000")
}

Try / catch

match decrypt(repo, &object, path, interactive) {
    Ok(obj) => apply(obj),
    Err(e) if e.to_string().contains("does not match its path or mode") => {
        eprintln!("envelope integrity failed; re-pulling from origin");
        repull_from_origin(path);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling decrypt (via commit_object) on an encrypted blob whose inner Plaintext.path differs from the outer envelope path, whose inner mode/scheme differs from the outer, whose path fails layout::is_safe_branch_path, or whose mode is not 100644/100755/120000.

Common situations: Hand-edited or partially merged encrypted files in the setup store; an attacker or a bad tool rewriting the envelope metadata; a symlink or special file with an unsupported mode being encrypted; path renames done on only one side of the envelope.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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