{"id":"97e574dc23697aab","repo":"sequelize/sequelize","slug":"unable-to-create-a-savepoint-without-the-transacti-97e574","errorCode":null,"errorMessage":"Unable to create a savepoint without the transaction object.","messagePattern":"Unable to create a savepoint without the transaction object\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mssql/src/query-interface-typescript.internal.ts","lineNumber":47,"sourceCode":"    transaction: Transaction,\n    _options: CommitTransactionOptions,\n  ): Promise<void> {\n    if (!transaction || !(transaction instanceof Transaction)) {\n      throw new Error('Unable to commit a transaction without the transaction object.');\n    }\n\n    const connection = transaction.getConnection() as MsSqlConnection;\n    await connection[ASYNC_QUEUE].enqueue(\n      async () =>\n        new Promise<void>((resolve, reject) => {\n          connection.commitTransaction(error => (error ? reject(error) : resolve()));\n        }),\n    );\n  }\n\n  async _createSavepoint(transaction: Transaction, options: CreateSavepointOptions): Promise<void> {\n    if (!transaction || !(transaction instanceof Transaction)) {\n      throw new Error('Unable to create a savepoint without the transaction object.');\n    }\n\n    const connection = transaction.getConnection() as MsSqlConnection;\n    await connection[ASYNC_QUEUE].enqueue(\n      async () =>\n        new Promise<void>((resolve, reject) => {\n          connection.saveTransaction(\n            error => (error ? reject(error) : resolve()),\n            options.savepointName,\n          );\n        }),\n    );\n  }\n\n  async _rollbackSavepoint(\n    transaction: Transaction,\n    options: RollbackSavepointOptions,\n  ): Promise<void> {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/sequelize/sequelize/blob/7e1deec499d5afbb8d1877c2f4d545cead1214ec/packages/mssql/src/query-interface-typescript.internal.ts#L29-L65","documentation":"Thrown by MsSqlQueryInterfaceTypescript._createSavepoint (packages/mssql/src/query-interface-typescript.internal.ts:47) when the parent transaction argument is missing or not a Transaction instance. Savepoints in MSSQL are issued through the parent transaction's connection, so Sequelize must hold a valid Transaction to call tedious's saveTransaction.","triggerScenarios":"Calling transaction.savePoint / _createSavepoint without passing the enclosing transaction, or passing a transaction that was already committed/rolled back and discarded.","commonSituations":"Building nested transactions manually and losing the parent reference; wrapping a helper that forgets to forward the transaction parameter; using an ORM helper that accepts an optional transaction which arrives as undefined.","solutions":["Always thread the parent transaction through to the savepoint call.","Use the managed nested API: sequelize.transaction(async t => { await sequelize.transaction({ transaction: t }, async () => { ... }); }).","Validate that the transaction is still active (t.finished === undefined) before creating a savepoint.","Avoid reusing a transaction variable after it has been committed/rolled back."],"exampleFix":"// before\nawait queryInterface._createSavepoint(undefined, { savepointName: 'sp1' }); // throws\n\n// after\nconst t = await sequelize.transaction();\nawait sequelize.transaction({ transaction: t }, async () => { /* savepoint scope */ });","handlingStrategy":"type-guard","validationCode":"import { Transaction } from '@sequelize/core';\nif (!(parent instanceof Transaction)) throw new Error('savepoint requires a parent Transaction');\nawait sequelize.transaction({ transaction: parent }, async () => { /* ... */ });","typeGuard":"import { Transaction } from '@sequelize/core';\nfunction isActiveTransaction(value: unknown): value is Transaction {\n  return value instanceof Transaction && value.finished === undefined;\n}","tryCatchPattern":"await sequelize.transaction({ transaction: parent }, async () => { await work(); }); // auto savepoint+rollback","preventionTips":["Use the nested managed transaction form so savepoints are created/rolled back automatically.","Always thread the parent transaction into nested calls.","Do not create savepoints on a transaction whose finished is set."],"tags":["mssql","transaction","savepoint"],"analyzedSha":"7e1deec499d5afbb8d1877c2f4d545cead1214ec","analyzedAt":"2026-08-03T18:58:44.549Z","schemaVersion":2}