libnyanpasu/clash-nyanpasu · error
managed target is not a file: {}
Error message
managed target is not a file: {} What it means
`path_hash` only knows how to hash regular files and symlinks (and treat absence as a sentinel hash). Any other entry type — a real directory, device node, FIFO, etc. — cannot be fingerprinted, so the function fails with this error. It indicates the managed profile path expected to be a file or symlink is actually something else, usually a directory.
Source
Thrown at backend/tauri/src/service/profile_file.rs:708
let target = std::fs::read_link(path)
.with_context(|| format!("read managed symlink {}", path.display()))?;
let target = target
.to_str()
.context("managed symlink target is not valid UTF-8")?;
Ok(hash_tagged(b"symlink", target.as_bytes()))
}
Ok(metadata) if is_symlink_or_reparse(&metadata) => {
bail!(
"managed target is an unsupported reparse point: {}",
path.display()
)
}
Ok(metadata) if metadata.is_file() => {
let content = std::fs::read(path)
.with_context(|| format!("read managed profile {}", path.display()))?;
Ok(hash_tagged(b"file", &content))
}
Ok(_) => bail!("managed target is not a file: {}", path.display()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
Ok(ABSENT_HASH.to_owned())
}
Err(error) => Err(error).with_context(|| format!("inspect {}", path.display())),
}
}
fn ensure_replaceable_target(path: &Path) -> anyhow::Result<()> {
match std::fs::symlink_metadata(path) {
Ok(metadata) if metadata.file_type().is_symlink() || metadata.is_file() => Ok(()),
Ok(metadata) if is_symlink_or_reparse(&metadata) => {
bail!(
"managed target is an unsupported reparse point: {}",
path.display()
)
}
Ok(_) => bail!("managed target is not replaceable: {}", path.display()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),View on GitHub (pinned to f7dbce2997)
Solutions
- Check the reported path; if it's an unexpected directory, move/backup its contents and remove it so the app can create the managed file/symlink
- Re-run profile materialization to recreate the expected file
- Adjust conflicting tooling (dotfile managers, other apps) that write directories to this path
- Verify you are pointing the profile at the intended file path, not a directory path
Example fix
// before: managed path is a directory ~/.config/clash/config.yaml/ (directory) // after mv ~/.config/clash/config.yaml ~/config.yaml.dir-backup # re-run materialization; app recreates config.yaml as a file
Defensive patterns
Strategy: validation
Validate before calling
fn managed_target_shape_ok(path: &std::path::Path) -> bool {
match std::fs::symlink_metadata(path) {
Ok(md) => md.is_file() || md.file_type().is_symlink(),
Err(e) => e.kind() == std::io::ErrorKind::NotFound,
}
}
// run before drift-check/materialization; a real directory fails this check Type guard
fn is_file_or_symlink(md: &std::fs::Metadata) -> bool {
md.is_file() || md.file_type().is_symlink()
} Try / catch
match path_hash(&managed) {
Err(e) if e.to_string().contains("not a file") => {
// path is a directory/other: back up and remove it, then re-run materialization
}
other => other?,
} Prevention
- Keep managed profile paths pointing at files, never directories
- Check for directory name collisions before installing other tools into the same location
- After schema/version migrations, verify entry types at managed paths
- Let the app create managed paths; do not pre-create them as folders
When it happens
Trigger: Drift verification calls `path_hash` on a managed path that `symlink_metadata` reports as a non-file, non-symlink entry (most commonly a directory). E.g. user replaced a managed profile file with a same-named folder.
Common situations: User created a directory where the app materializes a profile file; package managers or other tools installing directories at the same path; leftover state from a different app version that used directories.
Related errors
- refusing to remove directory as a profile resource: {}
- managed target is not replaceable: {}
- failed to allocate a unique runtime candidate after 16 attem
- runtime candidate directory is a symlink or reparse point: {
- runtime candidate path is not a private directory: {path}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/93904b034b1099f3.
Report an issue: GitHub.