tursodatabase/turso · error · Error

No active remote transaction

Error message

No active remote transaction

What it means

RemoteWriter.commitTransaction() (bindings/javascript/sync/packages/common/remote-writer.ts:90) sends COMMIT on the current session and throws when this.session is null - i.e. no BEGIN was executed (or the previous transaction already tore the session down in its finally block, which sets session = null). The writer models one session per remote transaction, so committing without a matching beginTransaction() is an invalid-state error.

Solutions

  1. Check writer.isInTransaction (or session presence) before committing and skip when false.
  2. Ensure every commitTransaction is paired with a successful beginTransaction on the same writer instance.
  3. Make cleanup idempotent: after rollback/commit in a finally, clear your own 'txn open' flag so later handlers do not commit again.
  4. If BEGIN failed, do not run the COMMIT branch of your transaction wrapper.

Example fix

// before
await writer.commitTransaction(); // no beginTransaction before it

// after
if (writer.isInTransaction) {
  await writer.commitTransaction();
}
Defensive patterns

Strategy: validation

Validate before calling

if (writer.isInRemoteTxn) {
  await writer.commitTransaction();
}

Type guard

const hasRemoteTransaction = (w: { isInTransaction: boolean }): boolean => w.isInTransaction;

Try / catch

try {
  await writer.commitTransaction();
} catch (e) {
  if (e instanceof Error && e.message === "No active remote transaction") {
    // nothing to commit: treat as already-closed and continue
  } else throw e;
}

Prevention

When it happens

Trigger: Calling commitTransaction() without a prior beginTransaction(mode); calling commit twice (the second finds session null after the first's finally reset); an error path that already closed the session (commit/rollback both null it in finally) followed by a cleanup routine that commits again; a state machine replaying COMMIT after a rollback.

Common situations: Sync-engine integrations where local transaction state and remote writer state drift (local COMMIT reaches the writer but the remote BEGIN was filtered or failed); error handlers that 'commit if not rolled back' racing with an earlier rollback; reusing one RemoteWriter across sequential transactions without re-beginning.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/6ca581a10a14fc15. Report an issue: GitHub.

Appendix: source

Thrown at bindings/javascript/sync/packages/common/remote-writer.ts:90

            await session.close();
        }
    }

    /**
     * Begin a remote transaction. Creates a session and sends BEGIN.
     */
    async beginTransaction(mode: string): Promise<void> {
        this.session = await this.createSession();
        await this.session.sequence("BEGIN " + mode);
        this._inRemoteTxn = true;
    }

    /**
     * Commit the remote transaction. Sends COMMIT and closes the session.
     */
    async commitTransaction(): Promise<void> {
        if (!this.session) {
            throw new Error("No active remote transaction");
        }
        try {
            await this.session.sequence("COMMIT");
        } finally {
            this._inRemoteTxn = false;
            await this.session.close();
            this.session = null;
        }
    }

    /**
     * Rollback the remote transaction. Sends ROLLBACK and closes the session.
     */
    async rollbackTransaction(): Promise<void> {
        if (!this.session) {
            throw new Error("No active remote transaction");
        }
        try {

View on GitHub (pinned to 244cde92a7)