jdx/mise · error
cannot encrypt non-file {}
Error message
cannot encrypt non-file {} What it means
During encrypted capture of tracked files, the code reads each live path and requires it to be a regular file (to read its bytes and record its blob mode). If the path is a directory, symlink-to-nothing, socket, or other non-file, it cannot be encrypted as a blob and capture bails naming the path.
Source
Thrown at src/system/history/shadow.rs:277
(
"120000",
path_bytes(&std::fs::read_link(&live)?).into_owned(),
)
} else if metadata.is_file() {
#[cfg(unix)]
let executable = {
use std::os::unix::fs::PermissionsExt;
metadata.permissions().mode() & 0o100 != 0
};
#[cfg(not(unix))]
let executable = false;
let bytes = crate::agecrypt::read_bounded(
std::fs::File::open(&live)?,
crate::agecrypt::MAX_PLAINTEXT_BYTES,
)?;
(if executable { "100755" } else { "100644" }, bytes)
} else {
bail!("cannot encrypt non-file {}", display_path(&live));
};
let path = format!(
"{}/{}",
root.label,
rel.to_str()
.ok_or_else(|| eyre::eyre!("non-UTF-8 tracked path"))?
.replace('\\', "/")
);
let fingerprint = blake3::keyed_hash(&cache_key, &bytes).to_hex().to_string();
let cached = cache.get(&path).filter(|entry| {
entry.fingerprint == fingerprint && entry.mode == mode && entry.scheme == scheme
});
let oid = match cached {
Some(entry)
if self
.blob_starts_with(&entry.oid, b"mise-encrypted-file-v1\n")
.unwrap_or(false) =>
{View on GitHub (pinned to afd2eddd3a)
Solutions
- Inspect the reported path and remove or correct it (or point tracking at a real file)
- If it is a symlink to a missing target, restore the target or drop the symlink
- If a directory now exists at the path, update the tracked paths/policy to target files within it
Example fix
// before: tracked path points at a directory
"secrets": { "path": "~/.config/secrets", "encrypt": true }
// after: track the actual files
"secrets": { "path": "~/.config/secrets/credentials.env", "encrypt": true } Defensive patterns
Strategy: validation
Validate before calling
// Rust: verify each tracked encrypt-path is a regular file before capture
for path in tracked_paths {
let meta = std::fs::symlink_metadata(&path)?;
anyhow::ensure!(meta.is_file(), "{} must be a regular file", path.display());
} Type guard
fn is_regular_file(p: &std::path::Path) -> bool {
std::fs::symlink_metadata(p).map(|m| m.is_file()).unwrap_or(false)
} Try / catch
match capture_tracked(&walk, recipients, interactive) {
Err(e) if e.to_string().contains("cannot encrypt non-file") => {
eprintln!("tracked path is not a regular file; fix or untrack it: {e}");
}
other => other?,
} Prevention
- Avoid tracking symlinks and special files with encrypt policies
- Re-check tracked paths after refactors that turn files into directories
- Run a pre-capture linter that stats every tracked path
When it happens
Trigger: capture_tracked_files encounters a tracked `encrypt`-policy path that resolves at capture time to a non-regular file (e.g. a directory or dangling symlink).
Common situations: A tracked path that was a file becomes a directory after a refactor; a symlink target was deleted; a named pipe or socket now occupies a previously-regular path.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- cannot capture non-file {}
- rustc output is not a regular file: {}
- failed to create file symlink: {err}
- {other:?}
- no age recipients to encrypt for
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/1e7b6996dae99225.
Report an issue: GitHub.