tursodatabase/turso · error · Error

database must be connected before execution the function

Error message

database must be connected before execution the function

What it means

Internal guard in maybePromise.must() (common/promise.ts:994). When db.prepare() is called on a Database that has not connected yet, the returned Statement wraps a lazy chain (connect -> native prepare) and only materializes once that promise resolves. Synchronous accessors such as stmt.columns() and the stmt.reader getter call stmt.must(), which throws this error while the underlying value is still null - i.e. before the connection/prepare finished.

Solutions

  1. Await the statement before using sync accessors: const stmt = await db.prepare(sql); stmt.columns().
  2. Or connect first: await db.connect(); then prepare - statements are materialized immediately (maybeValue path).
  3. Keep column introspection inside async functions only; never read .columns()/.reader from sync callbacks.
  4. In tests, make the prepare assertion async so the lazy chain settles before must() runs.

Example fix

// before
const stmt = db.prepare("SELECT 1"); // not awaited, db not connected yet
stmt.columns(); // throws: database must be connected

// after
const stmt = await db.prepare("SELECT 1"); // connect + prepare settled
stmt.columns();
Defensive patterns

Strategy: validation

Validate before calling

const stmt = await db.prepare(sql); // resolves connect + native prepare
stmt.columns(); // safe: statement materialized

Try / catch

try {
  stmt.columns();
} catch (e) {
  if (e instanceof Error && /must be connected/.test(e.message)) {
    // lazy chain not settled: await the statement, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling const stmt = db.prepare(sql) without awaiting, then immediately calling stmt.columns() or reading stmt.reader; using sync-style accessors on a lazily-connected (WASM/async IO) database; racing two operations where the connect promise has not settled yet; calling columns() inside a synchronous function that runs before the microtask queue flushes the connect+prepare chain.

Common situations: Porting sync API code (the compat API returns materialized statements) to the promise API where prepare returns a Promise-like Statement; framework code (e.g. a sync render path) touching stmt.columns() before an async effect completes; unit tests that forget to await the statement before introspecting columns.

Related errors


AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-20). Data as JSON: /api/errors/4dc22fa1ac7ce091. Report an issue: GitHub.

Appendix: source

Thrown at bindings/javascript/packages/common/promise.ts:1158

        fn(result);
        return result;
      }
    },
    async resolve() {
      if (promise != null) {
        return await promise;
      }
      let valueResolve, valueReject;
      promise = new Promise((resolve, reject) => {
        valueResolve = x => { resolve(x); value = x; }
        valueReject = reject;
      });
      await lazy().then(valueResolve, valueReject);
      return await promise;
    },
    must() {
      if (value == null) {
        throw new Error(`database must be connected before execution the function`)
      }
      return value;
    },
  }
}

function maybeValue<T>(value: T): MaybeLazy<T> {
  return {
    apply(fn) { fn(value); },
    resolve() { return Promise.resolve(value); },
    must() { return value; },
  }
}

/**
 * Statement represents a prepared SQL statement that can be executed.
 */
class Statement {

View on GitHub (pinned to c1e5928725)