jdx/mise · error
brew-cask: structured directory copy requires recursive=true
Error message
brew-cask: structured directory copy requires recursive=true
What it means
A structured copy step found its source path on disk, but the source is a directory and the step was declared without recursive=true. mise only copies directories when the recursive flag is set, mirroring Homebrew's single-file copy default, and aborts instead of guessing.
Source
Thrown at src/system/packages/brew/cask.rs:3446
.map(|guard| flight_guard_matches(cask, guard, staged_path, appdir))
.collect::<Result<Vec<_>>>()?
.into_iter()
.all(|matches| matches)
{
return Ok(());
}
let sources = flight_symlink_sources(cask, source, *source_glob, staged_path, appdir)?;
let [source] = sources.as_slice() else {
bail!("brew-cask: structured copy source must resolve to exactly one path");
};
if !source.exists() {
bail!(
"brew-cask: structured copy source '{}' was not found",
source.display()
);
}
if source.is_dir() && !recursive {
bail!("brew-cask: structured directory copy requires recursive=true");
}
let target = resolve_flight_path_with_context(cask, target, staged_path, appdir)?;
let external = !target.starts_with(staged_path);
let target_metadata = target.symlink_metadata().ok();
if target_metadata.is_some() {
if !overwrite {
bail!(
"brew-cask: structured copy target '{}' already exists",
target.display()
);
}
if external {
targets.protect(&target)?;
} else {
file::remove_all(&target)?;
}
}
if let Some(parent) = target.parent() {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Confirm the source is really a directory: ls -ld on the path from the error message
- If copying the whole directory is intended, add recursive=true to the copy artifact in the cask data (upstream fix)
- If a single file was intended, correct the source path to point at the file inside the bundle
- File an issue with homebrew-cask if the shipped metadata is missing the flag
Example fix
// before (cask artifact data)
copy { source: "payload/MyApp.app", recursive: false }
// after
copy { source: "payload/MyApp.app", recursive: true } Defensive patterns
Strategy: validation
Validate before calling
STAGED="$(brew --caskroom)/<token>/<version>" test -d "$STAGED/payload/MyApp.app" && echo "source is a directory: copy step needs recursive=true"
Prevention
- When authoring cask data, set recursive=true for any source that is or can become a bundle directory
- Remember .app/.appex are directories on macOS, not files
- Re-check copy flags after payload repackaging changes file/dir shapes
When it happens
Trigger: Calling mise install on a cask whose copy source resolves to a directory (any .app bundle, .appex, or plain folder in the staged tree) while the copy artifact lacks recursive=true; typically after a payload changed from a single file to a bundle directory.
Common situations: Upstream cask metadata regression that dropped the recursive flag; an archive repackaged so a formerly-flat file became a directory; macOS/Archive Utility re-packaging producing nested .app bundles during cask authoring.
Related errors
- brew-cask: structured copy source must resolve to exactly on
- brew-cask: structured copy source '{}' was not found
- brew-cask: refusing generic artifact source outside the extr
- brew-cask: refusing to stage generic artifact through a path
- brew-cask: unsupported generic artifact type: {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/f240c0b177532fb8.
Report an issue: GitHub.