{"record":{"id":"1342dc6c180299b8","repo":"jdx/mise","slug":"brew-cask-structured-file-operation-must-use-stag","errorCode":null,"errorMessage":"brew-cask: structured file operation must use staged_path","messagePattern":"brew-cask: structured file operation must use staged_path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask.rs","lineNumber":3964,"sourceCode":"                );\n            }\n            matches.push(path);\n        }\n    }\n    matches.sort();\n    matches.dedup();\n    Ok(matches)\n}\n\nfn is_flight_glob(path: &str) -> bool {\n    path.chars()\n        .any(|c| matches!(c, '*' | '?' | '[' | ']' | '{' | '}'))\n}\n\nfn resolve_flight_path(staged_path: &Path, path: &FlightPath) -> Result<PathBuf> {\n    match path.base {\n        FlightPathBase::StagedPath => {}\n        _ => bail!(\"brew-cask: structured file operation must use staged_path\"),\n    }\n    let relative = Path::new(&path.path);\n    validate_flight_relative_path(&path.path)?;\n    Ok(staged_path.join(relative))\n}\n\nfn resolve_flight_path_with_context(\n    cask: &Cask,\n    path: &FlightPath,\n    staged_path: &Path,\n    appdir: &Path,\n) -> Result<PathBuf> {\n    let expanded = expand_flight_template(cask, &path.path, staged_path, appdir);\n    match path.base {\n        FlightPathBase::StagedPath => {\n            validate_flight_relative_path(&expanded)?;\n            Ok(staged_path.join(expanded))\n        }","sourceCodeStart":3946,"sourceCodeEnd":3982,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/packages/brew/cask.rs#L3946-L3982","documentation":"`resolve_flight_path` only accepts paths whose base is `FlightPathBase::StagedPath`; it backs move and remove steps as well as non-contextual source resolution. A path carrying `AppDir`, `HomebrewPrefix` or `Literal` is rejected here: those bases are only translated by `resolve_flight_path_with_context` for the artifact types that support them.","triggerScenarios":"A move or remove step whose FlightPath was built with base AppDir, HomebrewPrefix or Literal; remove-step paths templated from `#{appdir}` or absolute prefixes.","commonSituations":"Ported Homebrew ruby stanzas that use absolute or appdir paths in move/remove positions; programmatic FlightPath construction defaulting to the wrong base.","solutions":["Express move and remove paths relative to the staged payload","Use artifact types that support contextual bases (copy or symlink) for appdir/prefix locations","Fix the base tag when constructing FlightPath values in code"],"exampleFix":"# before\nmove(source: \"#{appdir}/Old.app\", target: \"#{staged}/Old.app\")\n# after - move only operates inside the staged payload\nremove(path: \"Old.app\")","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Only staged-based paths may go through strict move/remove resolution\nfn is_staged_based(path: &FlightPath) -> bool {\n    matches!(path.base, FlightPathBase::StagedPath)\n}","tryCatchPattern":"if err.to_string().contains(\"must use staged_path\") {\n    // re-express the path relative to the staged payload or switch artifact type\n}","preventionTips":["Keep move/remove steps staged-relative by construction","Route appdir/prefix locations through copy or symlink artifacts, which accept context bases","Unit-test FlightPath construction so the base is never guessed"],"tags":["brew-cask","path-base","file-move","validation"],"backgroundTag":"invalid-base-path","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}