{"record":{"id":"8d210ca212e50370","repo":"dbt-labs/dbt-core","slug":"formula-path-has-no-filename","errorCode":null,"errorMessage":"formula path has no filename: {}","messagePattern":"formula path has no filename: (.+?)","errorType":"validation","errorClass":"anyhow","httpStatus":null,"severity":"error","filePath":"crates/dbt-ci/src/homebrew/publish.rs","lineNumber":49,"sourceCode":"        Ok(()) => ExitCode::SUCCESS,\n        Err(e) => {\n            eprintln!(\"error: {e:#}\");\n            ExitCode::from(2)\n        }\n    }\n}\n\nfn run(args: HomebrewPublishArgs) -> Result<()> {\n    validate_release_version(&args.version)\n        .with_context(|| format!(\"invalid --version {:?}\", args.version))?;\n    if !args.formula.is_file() {\n        bail!(\"formula file not found: {}\", args.formula.display());\n    }\n    let filename = args\n        .formula\n        .file_name()\n        .and_then(|s| s.to_str())\n        .ok_or_else(|| anyhow!(\"formula path has no filename: {}\", args.formula.display()))?\n        .to_string();\n    if !filename.ends_with(\".rb\") {\n        bail!(\"formula filename does not end in .rb: {filename}\");\n    }\n\n    let token = read_token(&args.token_env, args.dry_run)?;\n    // For HTTPS tap URLs, build an `http.extraHeader` config knob carrying\n    // Basic auth credentials. Non-HTTPS URLs (file://, ssh) carry their\n    // own auth.\n    let auth_args = build_auth_args(&args.tap_repo, token.as_deref());\n\n    let work = TempDir::new(\"dbt-ci-brew-publish\")?;\n    eprintln!(\"→ git clone {} -> {}\", args.tap_repo, work.path().display());\n    let mut clone_argv: Vec<OsString> = auth_args.clone();\n    clone_argv.push(\"clone\".into());\n    if !is_local_path(&args.tap_repo) {\n        clone_argv.push(\"--depth\".into());\n        clone_argv.push(\"1\".into());","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-ci/src/homebrew/publish.rs#L31-L67","documentation":"`run` in crates/dbt-ci/src/homebrew/publish.rs derives the Homebrew formula filename from the `--formula` path via `Path::file_name()`. If the path terminates in `..`, is the filesystem root (`/`), or is empty, `file_name()` returns None and the tool bails with this error. The filename is then validated to end in `.rb` before publishing to the tap.","triggerScenarios":"Passing `--formula /`, `--formula ..`, or a path whose last component is `..`/`.` so `Path::file_name()` yields None; also any path built programmatically from a directory rather than a file.","commonSituations":"A CI variable interpolating to an empty or root path; shell expansions collapsing a path to `/`; hand-writing a path ending in a trailing `/..`; pointing the publisher at a directory instead of the formula file.","solutions":["Pass the full path to the `.rb` formula file (e.g. `Formula/mytool.rb`), not a directory, `/`, or `..`.","Check the CI variable that supplies the formula path resolves to a real file.","If constructing the path in code, use `join(\"Formula.rs\")`-style explicit file names rather than directory-only components."],"exampleFix":"// before\nhomebrew publish --formula ./Formula/../\n// after\nhomebrew publish --formula ./Formula/dbt-cli.rb","handlingStrategy":"validation","validationCode":"let p = std::path::Path::new(&args.formula);\nif !p.is_file() || p.file_name().is_none() {\n    return Err(format!(\"--formula must be a file path, got: {}\", p.display()));\n}\nif p.extension() != Some(std::ffi::OsStr::new(\"rb\")) {\n    return Err(\"--formula must end in .rb\".into());\n}","typeGuard":"fn is_formula_path(p: &Path) -> bool {\n    p.file_name().is_some() && p.extension() == Some(std::ffi::OsStr::new(\"rb\"))\n}","tryCatchPattern":"match publish_homebrew(&args) {\n    Err(e) if e.to_string().contains(\"formula path\") => {\n        eprintln!(\"pass the full .rb file path, e.g. Formula/dbt-cli.rb\")\n    }\n    Err(e) => return Err(e),\n    Ok(v) => v,\n}","preventionTips":["Always pass the concrete .rb file path, never a directory or ..","In CI, echo the formula path before publishing to catch empty interpolation.","Validate the formula path exists early in the pipeline."],"tags":["homebrew","path","cli","release-pipeline"],"backgroundTag":"invalid-argument-value","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}