jdx/mise · error
brew-cask: : invalid path
Error message
brew-cask:{}: invalid {kind} {field} path {} What it means
When parsing a Homebrew cask's flight-plan artifact step (e.g. binary, pkg, or artifact move directives), each path must be a relative, well-formed path inside the staged area. `parse_flight_path` throws this error when `validate_flight_relative_path` rejects the `path` string in the cask's JSON artifact entry. It guards against absolute paths, `..` traversal, and other path components that would move files outside the staging area.
Solutions
- Inspect the cask JSON artifact entry and rewrite `path` as a plain relative path (no leading '/', no '..') that stays inside the staged area
- Report or fix the offending cask in its tap if upstream data is malformed
- If the path is legitimately external, use a different artifact kind/directive that supports it rather than a staged relative path
Example fix
// before (cask artifact JSON)
{ "type": "binary", "path": "/opt/homebrew/bin/foo" }
// after
{ "type": "binary", "path": "foo.app/Contents/MacOS/foo" } Defensive patterns
Strategy: validation
Validate before calling
// Rust: validate a cask artifact path before parsing
fn is_safe_relative_path(p: &str) -> bool {
!p.is_empty()
&& !p.starts_with('/')
&& std::path::Path::new(p)
.components()
.all(|c| matches!(c, std::path::Component::Normal(_)))
}
if !is_safe_relative_path(&artifact["path"].as_str().unwrap_or_default()) {
eprintln!("artifact path must be a clean relative path");
} Type guard
fn valid_flight_path(p: &&str) -> bool {
std::path::Path::new(p)
.components()
.all(|c| matches!(c, std::path::Component::Normal(_)))
} Prevention
- Author cask artifact paths as staged relative paths only (no leading '/', no '..')
- Lint cask JSON in your tap with a path validator in CI
- Prefer well-known absolute targets via dedicated directives rather than path fields
When it happens
Trigger: Calling parse_flight_path (via FlightStep::Move or parse_flight_step) on a cask JSON artifact whose `path` value fails validate_flight_relative_path — e.g. an absolute path like "/usr/local/bin/foo", a path containing "..", or an empty/rooted path.
Common situations: A third-party tap publishes a cask whose artifact stanza uses absolute paths or paths escaping the staged_path; a hand-edited or generated cask JSON; a Homebrew upstream format change producing paths this parser intentionally rejects.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- brew-cask: : git only_path must name a directory within the…
- brew-cask: invalid
- app target is outside an allowed Applications directory
- artifact target has changed
- binary target is not an owned Caskroom symlink
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/4397af13e9fa600c.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/artifacts.rs:1125
"brew-cask:{}: unsupported {kind} {field} metadata format",
cask.token
)
})?;
let base = match object.get("base").and_then(Value::as_str) {
Some("staged_path") => FlightPathBase::StagedPath,
Some(base) => bail!(
"brew-cask:{}: unsupported {kind} {field} base {}",
cask.token,
base
),
None => bail!("brew-cask:{}: unsupported {kind} {field} base", cask.token),
};
let path = object
.get("path")
.and_then(Value::as_str)
.ok_or_else(|| eyre!("brew-cask:{}: unsupported {kind} {field} path", cask.token))?;
if validate_flight_relative_path(path).is_err() {
bail!(
"brew-cask:{}: invalid {kind} {field} path {}",
cask.token,
path
)
}
Ok(FlightPath {
base,
path: path.to_string(),
})
}
/// `set_permissions` paths follow Homebrew's `remove` shape but may also
/// name the installed app for `postflight_steps`, so `appdir` is accepted
/// beside `staged_path`.
pub(super) fn parse_permissions_flight_path(
cask: &Cask,
kind: &str,
value: Option<&Value>,View on GitHub (pinned to 533346cc37)