jdx/mise · error
brew-cask: unsupported generic artifact type
Error message
brew-cask: unsupported generic artifact type: {} What it means
Thrown by copy_cask_artifact_at, the recursive copier used for cask `artifact` (generic) stanzas. It only knows three entry kinds: symlinks (recreated with symlinkat), directories (recreated with mkdirat and walked), and regular files (copied with openat O_EXCL then fchmod). Anything else staged at the printed path — a FIFO, unix socket, or device node — hits this bail and the install aborts.
Solutions
- Inspect the printed staged path with `ls -l` / `stat` to identify the non-regular entry (fifo, socket, device)
- Rebuild or re-download the cask payload shipping only regular files, directories, and symlinks
- If you control the cask, drop the special file from the archive and create it at runtime via the tool itself or a postflight step
- Report the cask token to its tap if the archive is upstream-broken
Example fix
# before: archive was built from a live dir and contains a socket $ tar -cf app.tar util/ # util/run.sock included # after: package regular files and symlinks only $ find util \( -type f -o -type l \) | tar -cf app.tar -T -
Defensive patterns
Strategy: validation
Validate before calling
// Before installing, walk the staged artifact tree and reject non-regular entries.
fn staged_tree_is_copyable(root: &std::path::Path) -> std::io::Result<()> {
let meta = root.symlink_metadata()?;
let ft = meta.file_type();
if ft.is_symlink() || ft.is_file() {
return Ok(());
}
if !ft.is_dir() {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput,
format!("unsupported artifact type: {}", root.display())));
}
for entry in std::fs::read_dir(root)? {
staged_tree_is_copyable(&entry?.path())?;
}
Ok(())
} Type guard
fn is_supported_artifact_entry(ft: &std::fs::FileType) -> bool {
ft.is_file() || ft.is_dir() || ft.is_symlink()
} Prevention
- Validate downloaded archives before staging: reject payloads containing sockets, fifos, or device nodes
- Build archives from a manifest of files rather than by tarring live directories
- Run a pre-install scan of the caskroom stage directory when integrating cask installs into automation
When it happens
Trigger: Installing a cask whose downloaded/staged archive contains a special file (mkfifo-created entry, socket, device node) anywhere in the artifact tree that copy_cask_artifact recurses into; reachable whenever the generic artifact source is copied into the target parent.
Common situations: Hand-built or repackaged cask archives that tar'd up a live directory containing sockets/fifos; archives produced on Linux with mknod entries; casks that worked under Homebrew's ruby installer because ruby's FileUtils skipped such entries silently.
Related errors
- brew-cask: : conflicts with installed cask
- brew-cask: : dependency cycle detected
- brew-cask: generic artifact backup changed directories
- brew-cask: generic artifact target
- brew-cask: : Homebrew owns this cask; remove it with…
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/220d94ab974e32b5.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask.rs:2090
copy_cask_artifact_at(&entry.path(), &fd, &entry.file_name())?;
}
nix::sys::stat::fchmod(&fd, mode)?;
} else if metadata.is_file() {
let destination = nix::fcntl::openat(
parent,
name,
nix::fcntl::OFlag::O_WRONLY
| nix::fcntl::OFlag::O_CREAT
| nix::fcntl::OFlag::O_EXCL
| nix::fcntl::OFlag::O_NOFOLLOW,
nix::sys::stat::Mode::S_IRUSR | nix::sys::stat::Mode::S_IWUSR,
)?;
let mut source = std::fs::File::open(from)?;
let mut destination = std::fs::File::from(destination);
copy_file_contents(&mut source, &mut destination)?;
nix::sys::stat::fchmod(&destination, mode)?;
} else {
bail!(
"brew-cask: unsupported generic artifact type: {}",
from.display()
);
}
Ok(())
}
#[cfg(all(unix, target_os = "macos"))]
fn copy_file_contents(from: &mut std::fs::File, to: &mut std::fs::File) -> Result<()> {
use std::os::fd::AsRawFd;
// SAFETY: both descriptors remain open for the call and fcopyfile does not
// retain them. A null state requests the default copyfile state.
let result = unsafe {
nix::libc::fcopyfile(
from.as_raw_fd(),
to.as_raw_fd(),
std::ptr::null_mut(),View on GitHub (pinned to 6f52dcdf99)