dbt-labs/dbt-core · error · anyhow

env var `{env_name}` is not set (required unless --dry-run)

Error message

env var `{env_name}` is not set (required unless --dry-run)

What it means

The Homebrew publish step aborts when the required token environment variable (e.g. a GitHub token) is unset or empty and the command was not run with --dry-run. read_token() in crates/dbt-ci/src/homebrew/publish.rs only returns Some(token) when the env var holds a non-empty value; in non-dry-run mode a missing value is a hard bail because publishing cannot authenticate. The dry-run flag is the explicit opt-out for local testing.

Source

Thrown at crates/dbt-ci/src/homebrew/publish.rs:127

        eprintln!("→ dry-run: skipping push. Patch follows:\n");
        run_git(Some(work.path()), &["--no-pager", "show", "HEAD"])?;
        return Ok(());
    }

    // Push needs the same `-c http.extraHeader=…` knobs as clone.
    let mut push_argv: Vec<OsString> = auth_args;
    push_argv.push("push".into());
    push_argv.push("origin".into());
    push_argv.push((&args.tap_branch).into());
    run_git_os(Some(work.path()), &push_argv)?;
    eprintln!("✓ pushed {filename} to {}", args.tap_repo);
    Ok(())
}

fn read_token(env_name: &str, dry_run: bool) -> Result<Option<String>> {
    let v = env::var(env_name).ok().filter(|v| !v.is_empty());
    if v.is_none() && !dry_run {
        bail!("env var `{env_name}` is not set (required unless --dry-run)");
    }
    Ok(v)
}

/// Builds `git -c http.extraHeader=Authorization: Basic <b64>` argv prefix
/// for HTTPS URLs. Returns an empty Vec for non-HTTPS URLs (file://, ssh) or
/// when no token is provided. The header is set via `-c` so it never enters
/// the URL — `git remote -v` and clone logs stay clean.
///
/// GitHub's git HTTP backend accepts Basic auth, not Bearer. The
/// `x-access-token` username is the convention `actions/checkout` uses
/// internally and works for both user PATs and GitHub App tokens.
fn build_auth_args(tap_url: &str, token: Option<&str>) -> Vec<OsString> {
    let Some(token) = token else {
        return Vec::new();
    };
    if !tap_url.starts_with("https://") {
        return Vec::new();

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Export the required token env var with a non-empty value in the environment running the publish command (e.g. `export HOMEBREW_GITHUB_TOKEN=ghp_...`).
  2. If this is a local test, re-run the command with --dry-run, which makes the token optional.
  3. In CI, verify the secret is defined in the repository settings and passed to the job via `env:` mapping in the workflow file.
  4. Check for typos between the env var name in the publish config and the name actually exported.

Example fix

// before
# .github/workflows/release.yml  (token never passed to the job)
- run: dbt-ci homebrew publish ...

// after
- run: dbt-ci homebrew publish ...
  env:
    HOMEBREW_GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
Defensive patterns

Strategy: validation

Validate before calling

import std::env;
fn ensure_token(env_name: &str, dry_run: bool) -> Result<(), String> {
    match env::var(env_name) {
        Ok(v) if !v.is_empty() => Ok(()),
        _ if dry_run => Ok(()),
        _ => Err(format!("set {env_name} or pass --dry-run before invoking publish")),
    }
}

Try / catch

match result {
    Err(e) if e.to_string().contains("is not set (required unless --dry-run)") => {
        eprintln!("hint: export {} or use --dry-run", env_name);
    }
    Err(e) => return Err(e),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: Running the homebrew publish command without --dry-run while the env var named by the config (e.g. HOMEBREW_GITHUB_TOKEN / GITHUB_TOKEN) is either not exported at all or exported as an empty string in the shell session that runs `run`.

Common situations: CI job that forgot to map the repository secret into the environment; running the publish command locally in a fresh shell where the token was only set in another profile; exporting the variable with `export FOO=` (empty) by mistake; a renamed env var after a workflow change.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/f995321cdaaaebbe. Report an issue: GitHub.