BoundaryML/baml · error

toolchain path points at the baml wrapper itself

Error message

toolchain path points at the baml wrapper itself: {}{origin}
Point at the {} binary instead, which is built alongside it.

What it means

Self-exec guard: a path selector points at the baml *wrapper* binary instead of the baml-cli toolchain binary that is built alongside it. Because both live in the same directory this is a one-character mistake; without the guard the wrapper would re-resolve the same path selector and exec itself forever (silent fork loop on unix). The check compares the candidate path against env::current_exe().

Solutions

  1. Change the selector to the baml-cli binary in the same directory as the wrapper
  2. Or run `baml toolchain use <path-to-baml-cli>` to record the corrected path
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at baml_language/crates/baml/src/main.rs:904 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/87e94feb97fe4ad4. Report an issue: GitHub.

Appendix: source

Thrown at baml_language/crates/baml/src/main.rs:904

    let text = String::from_utf8(output.stdout).ok()?;
    let line = text.lines().next()?.trim();
    (!line.is_empty()).then(|| line.to_string())
}

/// Refuse to exec the wrapper itself. `baml` and `baml-cli` are built into the
/// same directory, so pointing at the wrapper is a one-character slip; without
/// this it re-resolves the same selector and execs itself forever, silently on
/// unix and as an unbounded process tree everywhere else.
fn reject_self_exec(cli: &Path, origin: &str) -> Result<()> {
    let Ok(current) = env::current_exe() else {
        return Ok(());
    };
    let same = match (current.canonicalize(), cli.canonicalize()) {
        (Ok(current), Ok(cli)) => current == cli,
        _ => current == cli,
    };
    if same {
        return Err(anyhow!(
            "toolchain path points at the baml wrapper itself: {}{origin}\nPoint at the {} binary instead, which is built alongside it.",
            cli.display(),
            cli_exe_name()
        ));
    }
    Ok(())
}

/// Check that a path selector points at something runnable. `origin` is a
/// pre-formatted `set by ...` line, or empty when the path came straight from
/// the command line and needs no attribution.
fn verify_path_toolchain(cli: &Path, origin: &str) -> Result<()> {
    if cli.is_dir() {
        return Err(anyhow!(
            "toolchain path is a directory: {}{origin}\nPoint at the {} binary, e.g. {}",
            cli.display(),
            cli_exe_name(),
            cli.join("bin").join(cli_exe_name()).display()

View on GitHub (pinned to bd85ce9dee)