{"record":{"id":"4397af13e9fa600c","repo":"jdx/mise","slug":"brew-cask-invalid-kind-field-path-4397af","errorCode":null,"errorMessage":"brew-cask:{}: invalid {kind} {field} path {}","messagePattern":"brew-cask:(.+?): invalid (.+?) (.+?) path (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/artifacts.rs","lineNumber":1125,"sourceCode":"            \"brew-cask:{}: unsupported {kind} {field} metadata format\",\n            cask.token\n        )\n    })?;\n    let base = match object.get(\"base\").and_then(Value::as_str) {\n        Some(\"staged_path\") => FlightPathBase::StagedPath,\n        Some(base) => bail!(\n            \"brew-cask:{}: unsupported {kind} {field} base {}\",\n            cask.token,\n            base\n        ),\n        None => bail!(\"brew-cask:{}: unsupported {kind} {field} base\", cask.token),\n    };\n    let path = object\n        .get(\"path\")\n        .and_then(Value::as_str)\n        .ok_or_else(|| eyre!(\"brew-cask:{}: unsupported {kind} {field} path\", cask.token))?;\n    if validate_flight_relative_path(path).is_err() {\n        bail!(\n            \"brew-cask:{}: invalid {kind} {field} path {}\",\n            cask.token,\n            path\n        )\n    }\n    Ok(FlightPath {\n        base,\n        path: path.to_string(),\n    })\n}\n\n/// `set_permissions` paths follow Homebrew's `remove` shape but may also\n/// name the installed app for `postflight_steps`, so `appdir` is accepted\n/// beside `staged_path`.\npub(super) fn parse_permissions_flight_path(\n    cask: &Cask,\n    kind: &str,\n    value: Option<&Value>,","sourceCodeStart":1107,"sourceCodeEnd":1143,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/artifacts.rs#L1107-L1143","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (cask artifact JSON)\n{ \"type\": \"binary\", \"path\": \"/opt/homebrew/bin/foo\" }\n// after\n{ \"type\": \"binary\", \"path\": \"foo.app/Contents/MacOS/foo\" }","handlingStrategy":"validation","validationCode":"// Rust: validate a cask artifact path before parsing\nfn is_safe_relative_path(p: &str) -> bool {\n    !p.is_empty()\n        && !p.starts_with('/')\n        && std::path::Path::new(p)\n            .components()\n            .all(|c| matches!(c, std::path::Component::Normal(_)))\n}\nif !is_safe_relative_path(&artifact[\"path\"].as_str().unwrap_or_default()) {\n    eprintln!(\"artifact path must be a clean relative path\");\n}","typeGuard":"fn valid_flight_path(p: &&str) -> bool {\n    std::path::Path::new(p)\n        .components()\n        .all(|c| matches!(c, std::path::Component::Normal(_)))\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["homebrew","cask","path-validation","artifact-parsing"],"backgroundTag":"invalid-argument-format","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"}