What happens
In a bound dbt project, a warehouse-less sql_execute is never served by the dbt adapter. The dbt-first path in ensureDbtAdapter (packages/opencode/src/altimate/native/connections/register.ts) fails to create the adapter, returns null, and the call falls through to the connection registry. Nothing is surfaced, so it looks like the dbt path simply isn't there.
Why
packages/dbt-tools resolves @altimateai/dbt-integration 0.2.14, which starts its Python child through python-bridge@1.1.0. Under Bun that fails twice:
- Module load.
python-bridge runs bluebird.promisifyAll(require('child_process')), which reads ChildProcess.prototype.stdin with the wrong receiver. Bun throws TypeError: Cannot access invalid private field (evaluating 'this.#stdin'). Node doesn't.
- IPC. With the load patched, Bun's
node:child_process IPC to a non-JS child closes after the first message, so the next call fails with ERR_IPC_CHANNEL_CLOSED.
Reproduce, from packages/dbt-tools against a dbt project with a venv: bun -e 'const {create}=await import("./src/adapter.ts"); await create({projectRoot:"<project>", pythonPath:"<project>/.venv/bin/python", dbtIntegration:"corecommand", queryLimit:500})' → the #stdin TypeError.
Fix
@altimateai/dbt-integration 0.3.x vendors the bridge and speaks newline JSON over a plain fd-3 pipe, with no python-bridge or bluebird in the tree. Moving dbt-tools to ^0.3.13 makes the adapter start under Bun from source.
Still open after that: the compiled altimate binary bundles the library, and the vendored bridge looks for node_python_bridge.py next to its own module. Inside a compiled binary that is a virtual path (/$bunfs/root/node_python_bridge.py) that the Python child can't open. So the binary needs a library-side change as well (write the bundled script to a real directory when the resolved path isn't a readable file).
What happens
In a bound dbt project, a warehouse-less
sql_executeis never served by the dbt adapter. The dbt-first path inensureDbtAdapter(packages/opencode/src/altimate/native/connections/register.ts) fails to create the adapter, returnsnull, and the call falls through to the connection registry. Nothing is surfaced, so it looks like the dbt path simply isn't there.Why
packages/dbt-toolsresolves@altimateai/dbt-integration0.2.14, which starts its Python child throughpython-bridge@1.1.0. Under Bun that fails twice:python-bridgerunsbluebird.promisifyAll(require('child_process')), which readsChildProcess.prototype.stdinwith the wrong receiver. Bun throwsTypeError: Cannot access invalid private field (evaluating 'this.#stdin'). Node doesn't.node:child_processIPC to a non-JS child closes after the first message, so the next call fails withERR_IPC_CHANNEL_CLOSED.Reproduce, from
packages/dbt-toolsagainst a dbt project with a venv:bun -e 'const {create}=await import("./src/adapter.ts"); await create({projectRoot:"<project>", pythonPath:"<project>/.venv/bin/python", dbtIntegration:"corecommand", queryLimit:500})'→ the#stdinTypeError.Fix
@altimateai/dbt-integration0.3.x vendors the bridge and speaks newline JSON over a plain fd-3 pipe, with nopython-bridgeorbluebirdin the tree. Movingdbt-toolsto^0.3.13makes the adapter start under Bun from source.Still open after that: the compiled
altimatebinary bundles the library, and the vendored bridge looks fornode_python_bridge.pynext to its own module. Inside a compiled binary that is a virtual path (/$bunfs/root/node_python_bridge.py) that the Python child can't open. So the binary needs a library-side change as well (write the bundled script to a real directory when the resolved path isn't a readable file).