sequelize/sequelize · error · TypeError

Sequelize#rawQuery requires a string as the first parameter.

Error message

Sequelize#rawQuery requires a string as the first parameter.

What it means

queryRaw is the low-level variant of query that does *not* process replacements. It requires the first parameter to be a string so the dialect's bind-parameter mapper can scan it. Line 254 throws TypeError on any non-string input, catching mistakes where users route a sql expression or options object through queryRaw.

Source

Thrown at packages/core/src/sequelize.js:255

        '"sql" cannot be an object. Pass a string instead, and pass bind and replacement parameters through the "options" parameter',
      );
    }

    sql = sql.trim();

    if (options.replacements) {
      sql = injectReplacements(sql, this.dialect, options.replacements);
    }

    // queryRaw will throw if 'replacements' is specified, as a way to warn users that they are miusing the method.
    delete options.replacements;

    return this.queryRaw(sql, options);
  }

  async queryRaw(sql, options) {
    if (typeof sql !== 'string') {
      throw new TypeError('Sequelize#rawQuery requires a string as the first parameter.');
    }

    if (options != null && 'replacements' in options) {
      throw new TypeError(`Sequelize#rawQuery does not accept the "replacements" options.
Only bind parameters can be provided, in the dialect-specific syntax.
Use Sequelize#query if you wish to use replacements.`);
    }

    options = { ...this.options.query, ...options, bindParameterOrder: null };

    let bindParameters;
    if (options.bind != null) {
      const isBindArray = Array.isArray(options.bind);
      if (!isPlainObject(options.bind) && !isBindArray) {
        throw new TypeError(
          'options.bind must be either a plain object (for named parameters) or an array (for numeric parameters)',
        );
      }

View on GitHub (pinned to 7e1deec499)

Solutions

  1. Ensure the first argument is a string literal or template: `sequelize.queryRaw('SELECT $1', { bind: [1] })`.
  2. If you have a sql`` expression, use `sequelize.query()` instead — it will format the BaseSqlExpression for you.
  3. Coerce/validate dynamic SQL to a string before calling queryRaw.

Example fix

// before
await sequelize.queryRaw(sql`SELECT ${1}`); // sql expression is not a string

// after
await sequelize.query(sql`SELECT ${1}`); // use query() for sql expressions
// or:
await sequelize.queryRaw('SELECT $1', { bind: [1] });
Defensive patterns

Strategy: type-guard

Validate before calling

function assertRawSqlString(sql) {
  if (typeof sql !== 'string') {
    throw new TypeError('queryRaw requires a string; for sql expressions use query() instead.');
  }
  return sql;
}
await sequelize.queryRaw(assertRawSqlString(sql), { bind });

Type guard

function isRawQueryString(sql) {
  return typeof sql === 'string';
}

Try / catch

try {
  await sequelize.queryRaw(expr, { bind });
} catch (e) {
  if (/requires a string as the first parameter/.test(e.message)) {
    await sequelize.query(expr, { bind });
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `sequelize.queryRaw(someObject)`, `sequelize.queryRaw(number)`, or passing a BaseSqlExpression that should have gone through `query()` instead.

Common situations: Refactoring and accidentally switching a `query` call to `queryRaw` while still passing an expression; calling queryRaw on user input that was not coerced to a string.

Related errors


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