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 brew-cask structured copy step resolved its source to a directory, but the step was declared with recursive=false. The library refuses a shallow/ambiguous directory copy and requires the caller to opt in to recursive copying explicitly.

Source

Thrown at src/system/packages/brew/cask/flight.rs:660

            overwrite,
            source_glob,
            guards,
        } => {
            if !flight_guards_pass(cask, guards, staged_path, appdir)? {
                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 afd2eddd3a)

Solutions

  1. Set recursive: true on the Copy flight step.
  2. If only a single file is wanted, narrow the source path/glob to the specific file.
  3. Reconsider using a Symlink step instead of copying a large directory.

Example fix

// before
FlightStep::Copy { source: "MyApp.app", recursive: false, .. }
// after
FlightStep::Copy { source: "MyApp.app", recursive: true, .. }
Defensive patterns

Strategy: validation

Validate before calling

if source.is_dir() && !recursive {
    return Err(eyre!("set recursive=true to copy directory {}", source.display()));
}

Prevention

When it happens

Trigger: FlightStep::Copy { source: <dir>, recursive: false } where source resolves to a directory inside staged_path — typically a glob matching a bundle/directory, or a literal path that became a directory after an upstream change.

Common situations: Cask authors copying a .app bundle or plugin directory but forgetting recursive=true; a glob that used to match a file now matches a directory after a version bump.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/837fd4c1bb44c3db. Report an issue: GitHub.