sequelize/sequelize · error · Error

Unable to start a transaction without the transaction object

Error message

Unable to start a transaction without the transaction object.

What it means

Thrown by IBMiQueryInterface._startTransaction when the transaction argument is missing or not a Transaction instance. The start path needs the Transaction to obtain its ODBC connection and call connection.beginTransaction(), so a falsy/wrong-typed value is rejected.

Source

Thrown at packages/ibmi/src/query-interface.ts:31

export class IBMiQueryInterface<
  Dialect extends IBMiDialect = IBMiDialect,
> extends AbstractQueryInterface<Dialect> {
  readonly #internalQueryInterface: IBMiQueryInterfaceInternal;

  constructor(dialect: Dialect, internalQueryInterface?: IBMiQueryInterfaceInternal) {
    internalQueryInterface ??= new IBMiQueryInterfaceInternal(dialect);

    super(dialect, internalQueryInterface);
    this.#internalQueryInterface = internalQueryInterface;
  }

  async _startTransaction(
    transaction: Transaction,
    options: StartTransactionOptions,
  ): Promise<void> {
    if (!transaction || !(transaction instanceof Transaction)) {
      throw new Error('Unable to start a transaction without the transaction object.');
    }

    if (options) {
      rejectInvalidOptions(
        'startTransactionQuery',
        this.sequelize.dialect,
        START_TRANSACTION_QUERY_SUPPORTABLE_OPTIONS,
        this.sequelize.dialect.supports.startTransaction,
        options,
      );
    }

    const connection = transaction.getConnection() as IBMiConnection;
    await connection.beginTransaction();
    if (options.isolationLevel) {
      await transaction.setIsolationLevel(options.isolationLevel);
    }
  }

View on GitHub (pinned to 7e1deec499)

Solutions

  1. Use the public sequelize.transaction() API which constructs and forwards the Transaction correctly.
  2. If invoking _startTransaction manually, pass the Transaction instance from the sequelize transaction manager.
  3. Guard with instanceof Transaction before the call.

Example fix

// before
await qi._startTransaction(null, {});
// after
await sequelize.transaction(async t => {
  // _startTransaction(t, options) called internally
});
Defensive patterns

Strategy: type-guard

Validate before calling

import { Transaction } from '@sequelize/core';
if (!(transaction instanceof Transaction)) {
  throw new Error('startTransaction requires a Transaction instance');
}

Type guard

import { Transaction } from '@sequelize/core';
function isTransaction(v) { return v instanceof Transaction; }

Prevention

When it happens

Trigger: Internal invocation of _startTransaction with undefined/null or a non-Transaction value; typically only reached via a subclass, hook, or direct test usage.

Common situations: Subclassing QueryInterface incorrectly, calling the underscore method directly, or losing the Transaction handle in control flow.

Related errors


AI-assisted analysis of sequelize/sequelize@7e1deec499 (2026-08-03). Data as JSON: /data/errors/784de1ed29dc1886.json. Report an issue: GitHub.