jdx/mise · error
brew-cask: unsupported generic artifact type: {}
Error message
brew-cask: unsupported generic artifact type: {} What it means
When copying a generic cask artifact into protected staging (copy_cask_artifact_at), mise handles exactly two source kinds: directories (opened via openat in the branch above) and regular files (opened with O_NOFOLLOW|O_CREAT|O_EXCL and copied byte-for-byte). Any other file type — symlink, FIFO, socket, device — falls into the else branch and is refused with the source path.
Source
Thrown at src/system/packages/brew/cask.rs:1964
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 9dcfcaa0dc)
Solutions
- If you maintain the cask, materialize symlinks as real files before packaging (cp -L), or point the artifact stanza at the real file
- Otherwise report the cask to its tap — mise intentionally refuses to copy special files into protected locations
Example fix
# before (packaging) cd dist && zip -r tool.zip . # bin/tool is a symlink -> tool-1.2.3 # after cp -L bin/tool bin/tool.real && rm bin/tool && mv bin/tool.real bin/tool cd dist && zip -r tool.zip . # bin/tool is a regular file
Defensive patterns
Strategy: validation
Validate before calling
// Tap authors: assert artifact sources are regular files/dirs before publishing let ft = std::fs::symlink_metadata(&artifact_source)?.file_type(); assert!(ft.is_file() || ft.is_dir(), "generic artifact must be a real file or dir, got symlink/special");
Type guard
fn is_copyable_artifact(p: &Path) -> bool {
p.symlink_metadata().map_or(false, |m| m.is_file() || m.is_dir())
} Try / catch
Catch 'unsupported generic artifact type' and report that the cask ships a symlink/special file as its artifact; remediation is repackaging the tap, so fail with a clear pointer rather than retrying.
Prevention
- Dereference symlinks (cp -L) when zipping cask payloads
- Point artifact stanzas at real files; let mise create any links via proper binary stanza handling
When it happens
Trigger: A cask's generic artifact source inside the archive is a symlink or other special file rather than a real file or directory — e.g. a tap zipping a build directory where the shipped binary is a relative symlink to a versioned file.
Common situations: Hand-built internal casks that zip directories containing symlinks; artifacts whose 'binary' entry is a link into another part of the archive.
Related errors
- brew-cask: refusing generic artifact source outside the extr
- brew-cask: refusing to stage generic artifact through a path
- brew-cask:{}: dependency cycle detected
- brew-cask:{}: Homebrew owns this cask; remove it with Homebr
- brew-cask:{}: conflicts with installed cask {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/220d94ab974e32b5.
Report an issue: GitHub.