Bug
sqlite3 :memory: "SELECT 1+1;" returns exit code 1 with stderr sqlite3: Expected ArrayBuffer for the first argument. on every invocation. Affects at least 2.13.1 and 2.14.0.
Reproducer
import { Bash } from 'just-bash'
const bash = new Bash({ files: {}, cwd: '/' })
const result = await bash.exec("sqlite3 :memory: 'SELECT 1+1;'")
// stdout: ''
// stderr: 'sqlite3: Expected ArrayBuffer for the first argument.\n'
// exitCode: 1
Root cause
The sqlite3 command resolves its worker file via a function in the bundled chunk (paraphrased):
function resolveWorkerPath() {
const dir = dirname(fileURLToPath(import.meta.url)) // dist/bundle/chunks/
const p1 = join(dir, '../../commands/sqlite3/worker.js') // dist/commands/sqlite3/worker.js
if (existsSync(p1)) return p1
const p2 = join(dir, 'worker.js') // dist/bundle/chunks/worker.js ← WRONG
if (existsSync(p2)) return p2
const p3 = join(dir, '../../../dist/commands/sqlite3/worker.js')
if (existsSync(p3)) return p3
throw new Error("sqlite3 worker not found. Run 'pnpm build' to compile the worker.")
}
p1 (dist/commands/sqlite3/worker.js) does not exist in the published package — only dist/commands/sqlite3/worker.d.ts is present. So the resolver falls through to p2, which is dist/bundle/chunks/worker.js — the Python3 worker.
The Python3 worker's SyncBackend constructor immediately does new Int32Array(sharedBuffer) where sharedBuffer is undefined for sqlite3 inputs (sqlite3 passes dbBuffer, not sharedBuffer). This throws the "Expected ArrayBuffer" error, which is caught and surfaced as { success: false, error: "Expected ArrayBuffer for the first argument." }.
Smoking gun
dist/commands/sqlite3/
worker.d.ts ✅ present in published package
worker.js ❌ missing from published package
The type declaration exists, confirming worker.js was intentional — it was accidentally omitted from the build or publish step.
Workaround
Copy the following to dist/commands/sqlite3/worker.js after install (a minimal implementation using the already-bundled sql.js):
import { workerData, parentPort } from 'node:worker_threads'
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
async function main() {
const { protocolToken, dbBuffer, sql, options } = workerData
const SQL = await require('sql.js')()
const db = dbBuffer ? new SQL.Database(dbBuffer) : new SQL.Database()
const results = []
let hasModifications = false
try {
for (const r of db.exec(sql))
results.push({ columns: r.columns, rows: r.values })
hasModifications = db.getRowsModified() > 0
} catch (e) {
if (options?.bail) {
db.close()
return parentPort.postMessage({ protocolToken, success: false, error: e.message })
}
results.push({ type: 'error', error: e.message })
}
const updatedBuffer = (hasModifications && dbBuffer) ? db.export() : null
db.close()
parentPort.postMessage({ protocolToken, success: true, results, hasModifications, dbBuffer: updatedBuffer })
}
main().catch(e =>
parentPort.postMessage({ protocolToken: workerData?.protocolToken, success: false, error: e.message })
)
Note: this workaround omits any security sandbox that the real worker likely has — the Python3 worker uses WorkerDefenseInDepth, so the real sqlite3 worker probably does too.
Bug
sqlite3 :memory: "SELECT 1+1;"returns exit code 1 with stderrsqlite3: Expected ArrayBuffer for the first argument.on every invocation. Affects at least 2.13.1 and 2.14.0.Reproducer
Root cause
The sqlite3 command resolves its worker file via a function in the bundled chunk (paraphrased):
p1(dist/commands/sqlite3/worker.js) does not exist in the published package — onlydist/commands/sqlite3/worker.d.tsis present. So the resolver falls through top2, which isdist/bundle/chunks/worker.js— the Python3 worker.The Python3 worker's
SyncBackendconstructor immediately doesnew Int32Array(sharedBuffer)wheresharedBufferisundefinedfor sqlite3 inputs (sqlite3 passesdbBuffer, notsharedBuffer). This throws the "Expected ArrayBuffer" error, which is caught and surfaced as{ success: false, error: "Expected ArrayBuffer for the first argument." }.Smoking gun
The type declaration exists, confirming
worker.jswas intentional — it was accidentally omitted from the build or publish step.Workaround
Copy the following to
dist/commands/sqlite3/worker.jsafter install (a minimal implementation using the already-bundledsql.js):Note: this workaround omits any security sandbox that the real worker likely has — the Python3 worker uses
WorkerDefenseInDepth, so the real sqlite3 worker probably does too.