{"record":{"id":"7c6d9938135fa303","repo":"jdx/mise","slug":"brew-cask-structured-symlink-globs-must-use-stage-7c6d99","errorCode":null,"errorMessage":"brew-cask: structured symlink globs must use staged_path","messagePattern":"brew-cask: structured symlink globs must use staged_path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/flight.rs","lineNumber":993,"sourceCode":"        FlightGuard::IfExists(path) => {\n            Ok(resolve_flight_path_with_context(cask, path, staged_path, appdir)?.exists())\n        }\n        FlightGuard::UnlessExists(path) => {\n            Ok(!resolve_flight_path_with_context(cask, path, staged_path, appdir)?.exists())\n        }\n    }\n}\n\npub(super) fn flight_symlink_sources(\n    cask: &Cask,\n    source: &FlightPath,\n    source_glob: bool,\n    staged_path: &Path,\n    appdir: &Path,\n) -> Result<Vec<PathBuf>> {\n    if source_glob {\n        if source.base != FlightPathBase::StagedPath {\n            bail!(\"brew-cask: structured symlink globs must use staged_path\");\n        }\n        let pattern = expand_flight_template(cask, &source.path, staged_path, appdir);\n        return expand_staged_glob(staged_path, &pattern);\n    }\n    Ok(vec![resolve_flight_path_with_context(\n        cask,\n        source,\n        staged_path,\n        appdir,\n    )?])\n}\n\npub(super) fn create_flight_symlink(source: &Path, target: &Path, sudo: FlightSudo) -> Result<()> {\n    match sudo {\n        FlightSudo::Never => file::make_symlink(source, target).map(|_| ()),\n        FlightSudo::IfNeeded => make_symlink_elevating(source, target),\n        FlightSudo::Always => sudo::run(\"/bin/ln\", &symlink_command_args(source, target), &[]),\n    }","sourceCodeStart":975,"sourceCodeEnd":1011,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/flight.rs#L975-L1011","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the glob source's base to \"staged_path\" in the cask flight definition.","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.","If the source should not be a glob, remove the glob flag and use a literal staged-path source."],"exampleFix":"// before\n{ \"source\": { \"base\": \"appdir\", \"path\": \"*.app\" }, \"glob\": true }\n// after\n{ \"source\": { \"base\": \"staged_path\", \"path\": \"*.app\" }, \"glob\": true }","handlingStrategy":"validation","validationCode":"function validateGlobSource(step) {\n  if (step.glob && step.source.base !== 'staged_path') {\n    throw new Error(`glob source must use base 'staged_path', got '${step.source.base}'`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair glob:true with base staged_path in flight definitions.","Validate cask flight configs against the supported FlightPathBase values.","Do not copy literal-source stanzas into glob stanzas without adjusting the base."],"tags":["brew-cask","symlink","glob","invalid-config-value"],"backgroundTag":"invalid-config-value","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}