{"record":{"id":"87e94feb97fe4ad4","repo":"BoundaryML/baml","slug":"toolchain-path-points-at-the-baml-wrapper-itself-origin","errorCode":null,"errorMessage":"toolchain path points at the baml wrapper itself: {}{origin}\nPoint at the {} binary instead, which is built alongside it.","messagePattern":"toolchain path points at the baml wrapper itself: (.+?)(.+?)\nPoint at the (.+?) binary instead, which is built alongside it\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml/src/main.rs","lineNumber":904,"sourceCode":"    let text = String::from_utf8(output.stdout).ok()?;\n    let line = text.lines().next()?.trim();\n    (!line.is_empty()).then(|| line.to_string())\n}\n\n/// Refuse to exec the wrapper itself. `baml` and `baml-cli` are built into the\n/// same directory, so pointing at the wrapper is a one-character slip; without\n/// this it re-resolves the same selector and execs itself forever, silently on\n/// unix and as an unbounded process tree everywhere else.\nfn reject_self_exec(cli: &Path, origin: &str) -> Result<()> {\n    let Ok(current) = env::current_exe() else {\n        return Ok(());\n    };\n    let same = match (current.canonicalize(), cli.canonicalize()) {\n        (Ok(current), Ok(cli)) => current == cli,\n        _ => current == cli,\n    };\n    if same {\n        return Err(anyhow!(\n            \"toolchain path points at the baml wrapper itself: {}{origin}\\nPoint at the {} binary instead, which is built alongside it.\",\n            cli.display(),\n            cli_exe_name()\n        ));\n    }\n    Ok(())\n}\n\n/// Check that a path selector points at something runnable. `origin` is a\n/// pre-formatted `set by ...` line, or empty when the path came straight from\n/// the command line and needs no attribution.\nfn verify_path_toolchain(cli: &Path, origin: &str) -> Result<()> {\n    if cli.is_dir() {\n        return Err(anyhow!(\n            \"toolchain path is a directory: {}{origin}\\nPoint at the {} binary, e.g. {}\",\n            cli.display(),\n            cli_exe_name(),\n            cli.join(\"bin\").join(cli_exe_name()).display()","sourceCodeStart":886,"sourceCodeEnd":922,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml/src/main.rs#L886-L922","documentation":"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().","triggerScenarios":"Thrown at baml_language/crates/baml/src/main.rs:904 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Change the selector to the baml-cli binary in the same directory as the wrapper","Or run `baml toolchain use <path-to-baml-cli>` to record the corrected path"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}