jdx/mise · error

encrypted file does not match its path or mode

Error message

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

What it means

This validate() checks that an encrypted history blob is internally consistent: the inner plaintext header's path, mode, and scheme must match the outer envelope's, the path must be a safe branch path, and the mode must be a regular-file or symlink mode. If any of these disagree, the encrypted file has been tampered with, truncated, or produced by a mismatched writer, so mise rejects it with this error. It is called from decrypt before any decryption result is trusted.

Solutions

  1. Identify which history commit/object holds the mismatching blob (the path is in the message) and re-encrypt or drop that version from history.
  2. Re-pull or re-push the affected file so a fresh, consistent envelope is written.
  3. Check for manual edits to the history store and revert them; the envelope must never be hand-modified.
  4. If caused by a scheme/tool upgrade, upgrade or downgrade mise so writer and reader agree on the envelope scheme.
Defensive patterns

Strategy: validation

Validate before calling

# sanity-check the envelope for a tracked encrypted path before decrypting
mise dot cat <path> >/dev/null || echo 'envelope inconsistent — re-encrypt or re-sync this path'

Try / catch

if err.contains('does not match its path or mode') {
    // blob is corrupt/tampered: re-encrypt from source of truth, do not trust decrypted output
}

Prevention

When it happens

Trigger: `decrypt` in files.rs calls validate on a history object and the envelope's inner header disagrees with the outer envelope or expectations: inner.path != requested path, inner.mode != outer.mode, inner.scheme != outer.scheme, path fails layout::is_safe_branch_path, or mode is not 100644/100755/120000.

Common situations: A history blob was manually edited or re-parented under a different path; an encryption scheme upgrade left mixed old/new envelopes; a corrupted or partially written blob in the history store; an unsafe path (e.g. traversal-like) smuggled into an envelope.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: 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 533346cc37)