Skip to content

Commit ae31698

Browse files
committed
fix(onboarding): dbt runtime probe falls back through cmd.exe on Windows
Node's `execFile("dbt")` on Windows uses CreateProcess, which honours PATHEXT for `.exe` and `.com` but NOT `.cmd`/`.bat` — those need a shell. Some Windows dbt install layouts (older `pip install --user` script dirs, certain corporate distributions, some WSL-bridge shims) drop a `dbt.cmd` wrapper on PATH rather than `dbt.exe`. Without a fallback, those users would see `dbt: missing` on the template's "Build & query it" branch even when dbt is installed and on PATH. Fix: on Windows only, if the direct `execFile("dbt", ...)` misses, retry through `cmd.exe /c dbt --version`. cmd's own resolver honours the full PATHEXT so it finds any wrapper shape. Args are constant strings so there's no injection surface. macOS/Linux keep the single shell-less probe. Codex flagged this in the class-B sweep of `execFile` call sites. No Windows CI covers this branch yet, so verify manually if you touch it.
1 parent ea6ec07 commit ae31698

1 file changed

Lines changed: 17 additions & 1 deletion

File tree

‎packages/opencode/src/altimate/onboarding/tool-detection.ts‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,23 @@ export function _resetDbtRuntimeCacheForTests() {
5959
}
6060

6161
async function probe(): Promise<DbtRuntime> {
62-
const out = await tryExec("dbt", ["--version"], 5_000)
62+
// Node's `execFile("dbt")` on Windows uses CreateProcess, which honours
63+
// PATHEXT for `.exe`/`.com` but NOT `.cmd`/`.bat` (those need a shell).
64+
// Some Windows dbt install layouts (older `pip install --user`, certain
65+
// corporate distributions, WSL-bridge shims) drop a `dbt.cmd` wrapper
66+
// on PATH instead of `dbt.exe`. Without a fallback we'd tell those
67+
// users "dbt: missing" on the template's Build & query it branch even
68+
// when dbt is right there.
69+
//
70+
// Fix: on Windows, if the direct probe misses, retry through
71+
// `cmd.exe /c dbt --version` — cmd's own resolver honours the full
72+
// PATHEXT (including `.cmd`/`.bat`) and finds any of the wrapper
73+
// shapes. Args are constant strings so there's no injection surface.
74+
// On macOS/Linux we skip the retry — one shell-less probe is enough.
75+
let out = await tryExec("dbt", ["--version"], 5_000)
76+
if (!out.ok && process.platform === "win32") {
77+
out = await tryExec("cmd.exe", ["/c", "dbt", "--version"], 5_000)
78+
}
6379
if (!out.ok) return { hasDbt: false, hasDbtDuckdb: false }
6480

6581
// dbt --version on 1.x prints something like:

0 commit comments

Comments
 (0)