dbt-labs/dbt-core · error · anyhow
formula path has no filename: {}
Error message
formula path has no filename: {} What it means
`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.
Source
Thrown at crates/dbt-ci/src/homebrew/publish.rs:49
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("error: {e:#}");
ExitCode::from(2)
}
}
}
fn run(args: HomebrewPublishArgs) -> Result<()> {
validate_release_version(&args.version)
.with_context(|| format!("invalid --version {:?}", args.version))?;
if !args.formula.is_file() {
bail!("formula file not found: {}", args.formula.display());
}
let filename = args
.formula
.file_name()
.and_then(|s| s.to_str())
.ok_or_else(|| anyhow!("formula path has no filename: {}", args.formula.display()))?
.to_string();
if !filename.ends_with(".rb") {
bail!("formula filename does not end in .rb: {filename}");
}
let token = read_token(&args.token_env, args.dry_run)?;
// For HTTPS tap URLs, build an `http.extraHeader` config knob carrying
// Basic auth credentials. Non-HTTPS URLs (file://, ssh) carry their
// own auth.
let auth_args = build_auth_args(&args.tap_repo, token.as_deref());
let work = TempDir::new("dbt-ci-brew-publish")?;
eprintln!("→ git clone {} -> {}", args.tap_repo, work.path().display());
let mut clone_argv: Vec<OsString> = auth_args.clone();
clone_argv.push("clone".into());
if !is_local_path(&args.tap_repo) {
clone_argv.push("--depth".into());
clone_argv.push("1".into());View on GitHub (pinned to 0267ce9170)
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.
Example fix
// before homebrew publish --formula ./Formula/../ // after homebrew publish --formula ./Formula/dbt-cli.rb
Defensive patterns
Strategy: validation
Validate before calling
let p = std::path::Path::new(&args.formula);
if !p.is_file() || p.file_name().is_none() {
return Err(format!("--formula must be a file path, got: {}", p.display()));
}
if p.extension() != Some(std::ffi::OsStr::new("rb")) {
return Err("--formula must end in .rb".into());
} Type guard
fn is_formula_path(p: &Path) -> bool {
p.file_name().is_some() && p.extension() == Some(std::ffi::OsStr::new("rb"))
} Try / catch
match publish_homebrew(&args) {
Err(e) if e.to_string().contains("formula path") => {
eprintln!("pass the full .rb file path, e.g. Formula/dbt-cli.rb")
}
Err(e) => return Err(e),
Ok(v) => v,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- formula file not found: {}
- formula filename does not end in .rb: {filename}
- --commit-author and --commit-email must be set together
- env var `{env_name}` is not set (required unless --dry-run)
- `git {}` exited with status {}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/8d210ca212e50370.
Report an issue: GitHub.