{"record":{"id":"6ca581a10a14fc15","repo":"tursodatabase/turso","slug":"no-active-remote-transaction","errorCode":null,"errorMessage":"No active remote transaction","messagePattern":"No active remote transaction","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"bindings/javascript/sync/packages/common/remote-writer.ts","lineNumber":90,"sourceCode":"            await session.close();\n        }\n    }\n\n    /**\n     * Begin a remote transaction. Creates a session and sends BEGIN.\n     */\n    async beginTransaction(mode: string): Promise<void> {\n        this.session = await this.createSession();\n        await this.session.sequence(\"BEGIN \" + mode);\n        this._inRemoteTxn = true;\n    }\n\n    /**\n     * Commit the remote transaction. Sends COMMIT and closes the session.\n     */\n    async commitTransaction(): Promise<void> {\n        if (!this.session) {\n            throw new Error(\"No active remote transaction\");\n        }\n        try {\n            await this.session.sequence(\"COMMIT\");\n        } finally {\n            this._inRemoteTxn = false;\n            await this.session.close();\n            this.session = null;\n        }\n    }\n\n    /**\n     * Rollback the remote transaction. Sends ROLLBACK and closes the session.\n     */\n    async rollbackTransaction(): Promise<void> {\n        if (!this.session) {\n            throw new Error(\"No active remote transaction\");\n        }\n        try {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/javascript/sync/packages/common/remote-writer.ts#L72-L108","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check writer.isInTransaction (or session presence) before committing and skip when false.","Ensure every commitTransaction is paired with a successful beginTransaction on the same writer instance.","Make cleanup idempotent: after rollback/commit in a finally, clear your own 'txn open' flag so later handlers do not commit again.","If BEGIN failed, do not run the COMMIT branch of your transaction wrapper."],"exampleFix":"// before\nawait writer.commitTransaction(); // no beginTransaction before it\n\n// after\nif (writer.isInTransaction) {\n  await writer.commitTransaction();\n}","handlingStrategy":"validation","validationCode":"if (writer.isInRemoteTxn) {\n  await writer.commitTransaction();\n}","typeGuard":"const hasRemoteTransaction = (w: { isInTransaction: boolean }): boolean => w.isInTransaction;","tryCatchPattern":"try {\n  await writer.commitTransaction();\n} catch (e) {\n  if (e instanceof Error && e.message === \"No active remote transaction\") {\n    // nothing to commit: treat as already-closed and continue\n  } else throw e;\n}","preventionTips":["Pair every commit with a successful beginTransaction on the same writer.","Check isInTransaction before terminal operations.","Make transaction cleanup idempotent with a settled flag."],"tags":["sync","remote","transaction","session","state"],"backgroundTag":"transaction-not-started","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}