jdx/mise · error
brew-cask: structured copy source
Error message
brew-cask: structured copy source '{}' was not found What it means
The copy step's source resolved to exactly one path, but that path does not exist on disk (`Path::exists()` follows symlinks, so a dangling symlink also triggers this). The check runs before any target handling, so nothing is created for an absent source.
Solutions
- Inspect the staged directory and correct the `source` string to the real file name
- Use the installer's template variables for version-stamped names so the path stays valid across releases
- Re-stage the payload (remove the caskroom staging dir, reinstall) to rule out partial extraction
- If the file is optional, guard the step with `if_exists` on the source
Example fix
# before
copy(source: "bin/mytool-v1.2", target: "#{staged}/bin/mytool")
# after
copy(source: "bin/mytool-#{version}", target: "#{staged}/bin/mytool") Defensive patterns
Strategy: validation
Validate before calling
// Verify the resolved copy source exists before executing the step
let source = resolve_flight_path_with_context(cask, &step.source, staged_path, appdir)?;
if !source.exists() {
return Err(eyre!("copy source '{}' missing in staged payload; re-stage the cask", source.display()));
} Try / catch
if err.to_string().contains("copy source") && err.to_string().contains("was not found") {
// trigger a re-download/re-stage and retry once before surfacing to the user
} Prevention
- Use version templates instead of hard-coded file names
- Verify staged payload contents when the cask definition is written
- Treat partial extraction as a first hypothesis: check the caskroom directory size
When it happens
Trigger: A non-glob `copy` whose source string names a file missing from the staged payload; a source that is a dangling symlink; template expansion producing a different name than what was staged.
Common situations: Upstream renamed the file between cask versions; partial or failed extraction of the staged archive; case-sensitive filesystem versus an archive built on macOS; typo in the source path.
Related errors
- brew-cask: completion artifact
- brew-cask: structured copy source must resolve to exactly…
- brew-cask: structured copy target
- brew-cask: structured directory copy requires recursive=true
- brew-cask: structured move source
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/3b34788292462e8d.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask.rs:3566
overwrite,
source_glob,
guards,
} => {
if !guards
.iter()
.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 {View on GitHub (pinned to 6f52dcdf99)