tursodatabase/turso · error · Error

transactionAsync is not supported with remoteWritesExperimen

Error message

transactionAsync is not supported with remoteWritesExperimental yet; use the deprecated transaction() for now

What it means

The WASM promise wrapper's transactionAsync() override throws when the database was opened with DatabaseOpts.remoteWritesExperimental. Remote-writes transactions run entirely on the remote server, so there is no local connection to hand to the callback as a Transaction handle. The library rejects the call up front instead of silently running the transaction in the wrong place. The doc comment on the override states this limitation explicitly.

Source

Thrown at bindings/javascript/sync/packages/wasm/promise-turbopack-hack.ts:333

        Object.defineProperties(properties.immediate.value, properties);
        Object.defineProperties(properties.exclusive.value, properties);
        return properties.default.value as TransactionFunction<F>;
    }

    /**
     * Returns a function that executes the given function in a transaction
     * on a connection owned for the whole BEGIN..COMMIT window; the callback
     * receives a {@link Transaction} handle as its first argument.
     *
     * Not supported together with {@link DatabaseOpts.remoteWritesExperimental}
     * yet: remote-writes transactions run on the remote server and have no
     * local connection to hand out.
     */
    override transactionAsync<F extends (txn: Transaction, ...args: any[]) => Promise<any>>(
        fn: F,
    ): AsyncTransactionFunction<F> {
        if (this.#remoteWriter) {
            throw new Error(
                "transactionAsync is not supported with remoteWritesExperimental yet; use the deprecated transaction() for now",
            );
        }
        return super.transactionAsync(fn);
    }

    /**
     * close the database and relevant files
     */
    async close() {
        if (this.#remoteWriter) {
            await this.#remoteWriter.close();
        }
        if (this.#engine != null) {
            if (this.name != null && this.#worker != null) {
                await Promise.all([
                    unregisterFileAtWorker(this.#worker, this.name),
                    unregisterFileAtWorker(this.#worker, `${this.name}-wal`),

View on GitHub (pinned to bad083fafb)

Solutions

  1. Switch the call to the deprecated db.transaction(fn) — its override detects the remote writer and routes the whole BEGIN..COMMIT to the remote server via remoteWriter.beginTransaction/commit
  2. Branch on the config you constructed the database with: use transaction(fn) when remoteWritesExperimental is set, transactionAsync(fn) otherwise
  3. If the Transaction-handle API is a hard requirement, drop remoteWritesExperimental and use local writes plus push() to synchronize

Example fix

// before
const db = new Database("app.db", { url, authToken, remoteWritesExperimental: true });
const tx = db.transactionAsync(async (txn) => { await txn.execute("INSERT ..."); }); // throws

// after
const db = new Database("app.db", { url, authToken, remoteWritesExperimental: true });
const tx = db.transaction(async () => { await db.execute("INSERT ..."); }); // runs BEGIN..COMMIT on the remote
Defensive patterns

Strategy: validation

Validate before calling

// Decide up front, from the opts you control, which transaction API is legal
const opts: DatabaseOpts = { url, authToken, remoteWritesExperimental: true };
const db = new Database(path, opts);

function makeTxn<T extends (...args: any[]) => Promise<any>>(db: Database, fn: T) {
  return opts.remoteWritesExperimental
    ? db.transaction(fn)        // remote-aware override
    : db.transactionAsync(fn); // local connection handle OK
}

Prevention

When it happens

Trigger: Constructing the database with `new Database(path, { url, authToken, remoteWritesExperimental: true })` and then calling `db.transactionAsync(async (txn) => { ... })`. The throw happens synchronously inside transactionAsync() as soon as the #remoteWriter is present, before any transaction work starts.

Common situations: Enabling remoteWritesExperimental on an existing app that already used transactionAsync; upgrading @tursodatabase/sync-wasm to a version where remoteWritesExperimental was introduced; copying transactionAsync examples from the local-sync docs into a remote-writes deployment; sharing transaction helper code between local and remote-writes databases.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/73d67155859dc7b2. Report an issue: GitHub.