jdx/mise · error

brew-cask: structured symlink globs must use staged_path

Error message

brew-cask: structured symlink globs must use staged_path

What it means

Structured symlink steps that declare their source as a glob must anchor that glob to the staged cask path (FlightPathBase::StagedPath). If a glob source specifies any other base, flight_symlink_sources rejects it immediately, because expanding globs outside the staged directory could match and link arbitrary user files.

Solutions

  1. Change the glob source's base to "staged_path" in the cask flight definition.
  2. If the intent was to link from the appdir, move the glob pattern to include the staged-path-relative location of the .app bundle instead.
  3. If the source should not be a glob, remove the glob flag and use a literal staged-path source.

Example fix

// before
{ "source": { "base": "appdir", "path": "*.app" }, "glob": true }
// after
{ "source": { "base": "staged_path", "path": "*.app" }, "glob": true }
Defensive patterns

Strategy: validation

Validate before calling

function validateGlobSource(step) {
  if (step.glob && step.source.base !== 'staged_path') {
    throw new Error(`glob source must use base 'staged_path', got '${step.source.base}'`);
  }
}

Prevention

When it happens

Trigger: execute_flight_step calls flight_symlink_sources with source_glob=true; the function checks source.base != FlightPathBase::StagedPath and bails — i.e. the cask flight step set a glob source whose base is appdir or another non-staged base.

Common situations: A hand-written or third-party cask flight config declares { "source": { "base": "appdir", "glob": "*.app" } }; a config migration changed the base field; copy-pasting a literal-source stanza and adding glob:true without adjusting the base.

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@533346cc37 (2026-09-17). Data as JSON: /api/errors/7c6d9938135fa303. Report an issue: GitHub.

Appendix: source

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

        FlightGuard::IfExists(path) => {
            Ok(resolve_flight_path_with_context(cask, path, staged_path, appdir)?.exists())
        }
        FlightGuard::UnlessExists(path) => {
            Ok(!resolve_flight_path_with_context(cask, path, staged_path, appdir)?.exists())
        }
    }
}

pub(super) fn flight_symlink_sources(
    cask: &Cask,
    source: &FlightPath,
    source_glob: bool,
    staged_path: &Path,
    appdir: &Path,
) -> Result<Vec<PathBuf>> {
    if source_glob {
        if source.base != FlightPathBase::StagedPath {
            bail!("brew-cask: structured symlink globs must use staged_path");
        }
        let pattern = expand_flight_template(cask, &source.path, staged_path, appdir);
        return expand_staged_glob(staged_path, &pattern);
    }
    Ok(vec![resolve_flight_path_with_context(
        cask,
        source,
        staged_path,
        appdir,
    )?])
}

pub(super) fn create_flight_symlink(source: &Path, target: &Path, sudo: FlightSudo) -> Result<()> {
    match sudo {
        FlightSudo::Never => file::make_symlink(source, target).map(|_| ()),
        FlightSudo::IfNeeded => make_symlink_elevating(source, target),
        FlightSudo::Always => sudo::run("/bin/ln", &symlink_command_args(source, target), &[]),
    }

View on GitHub (pinned to 533346cc37)