jdx/mise · error · eyre::Report
unsupported host path type: {}
Error message
unsupported host path type: {} What it means
build_layer_from_path classifies the source by its file type (via symlink_metadata, so symlinks are detected as such). Only regular files, symlinks, and directories are supported; anything else — FIFO, unix socket, block/char device — hits this guard. The tar layer has no meaningful, portable representation for those types.
Source
Thrown at src/oci/layer.rs:141
eyre::bail!("cannot copy a file or symlink to the image root");
}
if image_path.ends_with('/') {
eyre::bail!(
"copy image path {image_path:?} ends with `/` but {} is not a directory; \
specify the exact destination file name",
host_path.display()
);
}
let kind = if metadata.file_type().is_symlink() {
EntryKind::Symlink(
std::fs::read_link(host_path)
.wrap_err_with(|| format!("reading symlink {}", host_path.display()))?,
)
} else if metadata.is_file() {
EntryKind::File
} else {
eyre::bail!("unsupported host path type: {}", host_path.display());
};
let mode = match &kind {
EntryKind::Symlink(_) => 0o777,
EntryKind::File if file_is_executable(host_path, &metadata) => 0o755,
EntryKind::File => 0o644,
EntryKind::Dir => unreachable!(),
};
let target_path = Path::new(target);
let rel = target_path
.file_name()
.map(PathBuf::from)
.ok_or_else(|| eyre::eyre!("copy image path has no file name: {image_path}"))?;
let prefix = target_path
.parent()
.unwrap_or_else(|| Path::new(""))
.to_string_lossy();
let size = if matches!(kind, EntryKind::Symlink(_)) {
0View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Point the entry at the real file or directory you intended, not the socket/fifo.
- Exclude runtime artifacts (sockets, fifos) from the source set before building.
- If you need a socket in the image, create it at container start (entrypoint), not by copying from the host.
Example fix
# before files = [ "/var/run/docker.sock:/run/docker.sock" ] # after # do not copy sockets; create at runtime, e.g. via entrypoint files = [ "./run-wrapper.sh:/usr/local/bin/run-wrapper.sh" ]
Defensive patterns
Strategy: validation
Validate before calling
import os, stat, sys
for src, _ in copy_entries.items():
m = os.lstat(src).st_mode
kind = stat.S_IFMT(m)
if kind not in (stat.S_IFREG, stat.S_IFLNK, stat.S_IFDIR):
sys.exit(f"unsupported source type (fifo/socket/device): {src}") Type guard
fn is_layer_supported(p: &Path) -> bool {
matches!(std::fs::symlink_metadata(p)
.map(|m| m.file_type())
.map(|ft| ft.is_file() || ft.is_symlink() || ft.is_dir()), Ok(true))
} Prevention
- Do not glob over /tmp, /var/run, or other runtime dirs containing sockets and fifos.
- Keep dotfiles repos free of mkfifo/socket artifacts (check with `find . ! -type f ! -type d ! -type l`).
- Create sockets/pipes at container runtime, never by layering host files.
When it happens
Trigger: A copy entry whose source is a named pipe (mkfifo), a listening unix socket file (e.g. /var/run/docker.sock on hosts where it's a socket rather than a symlink), or a device node.
Common situations: Broad globbing over a directory that happens to include runtime sockets/pipes; copying /var/run or /tmp contents into an image; leftover fifo artifacts in a dotfiles repo.
Related errors
- not a directory: {}
- cannot copy a file or symlink to the image root
- copy image path {image_path:?} ends with `/` but {} is not a
- cannot create nested task stubs because {} is not a director
- cannot write task stub because {} is not a regular file
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/5af828070b8db6af.
Report an issue: GitHub.