sequelize/sequelize · error · Error

Query includes bind parameter "$${parameterName}", but no va

Error message

Query includes bind parameter "$${parameterName}", but no value has been provided for that bind parameter.

What it means

When options.bind is an array, queryRaw maps each $N token in the SQL to bind[N-1]. Line 286 throws if a parameter name is non-numeric or if its index exceeds the array length — i.e. the SQL references a positional bind the caller did not supply. This catches SQL/bind mismatches before they reach the driver.

Source

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

      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)',
        );
      }

      const isOracleBulkBind = this.dialect.name === 'oracle' && isBindArray && options.executeMany;

      if (isOracleBulkBind) {
        // skip mapBindParameters and all bind name validation
        // oracle driver executeMany() expects this format
        bindParameters = options.bind;
      } else {
        const mappedResult = mapBindParameters(sql, this.dialect);

        for (const parameterName of mappedResult.parameterSet) {
          if (isBindArray) {
            if (!/[1-9][0-9]*/.test(parameterName) || options.bind.length < Number(parameterName)) {
              throw new Error(
                `Query includes bind parameter "$${parameterName}", but no value has been provided for that bind parameter.`,
              );
            }
          } else if (!(parameterName in options.bind)) {
            throw new Error(
              `Query includes bind parameter "$${parameterName}", but no value has been provided for that bind parameter.`,
            );
          }
        }

        sql = mappedResult.sql;

        // used by dialects that support "INOUT" parameters to map the OUT parameters back to the name the dev used.
        options.bindParameterOrder = mappedResult.bindOrder;
        if (mappedResult.bindOrder == null) {
          bindParameters = options.bind;
        } else {
          bindParameters = mappedResult.bindOrder.map(key => {

View on GitHub (pinned to 7e1deec499)

Solutions

  1. Count placeholders in the SQL and ensure the bind array has at least that many entries in the right order.
  2. If the SQL uses named tokens ($name), pass a plain object for bind instead of an array.
  3. Generate both SQL and bind list from the same source (e.g. a query builder) so they cannot drift.

Example fix

// before
await sequelize.queryRaw('SELECT $1, $2, $3', { bind: [10, 20] }); // missing $3

// after
await sequelize.queryRaw('SELECT $1, $2, $3', { bind: [10, 20, 30] });
Defensive patterns

Strategy: validation

Validate before calling

function assertArrayBindCoversSql(sql, bind) {
  const tokens = [...sql.matchAll(/\$(\d+)/g)].map(m => Number(m[1]));
  const max = tokens.length ? Math.max(...tokens) : 0;
  if (bind.length < max) {
    throw new Error(`SQL references $${max} but bind array length is ${bind.length}.`);
  }
  return bind;
}
await sequelize.queryRaw(sql, { bind: assertArrayBindCoversSql(sql, bind) });

Type guard

function arrayBindMatchesSql(sql, bind) {
  const tokens = [...sql.matchAll(/\$(\d+)/g)].map(m => Number(m[1]));
  const max = tokens.length ? Math.max(...tokens) : 0;
  return Array.isArray(bind) && bind.length >= max;
}

Try / catch

try {
  await sequelize.queryRaw(sql, { bind });
} catch (e) {
  if (/no value has been provided for that bind parameter/.test(e.message) && Array.isArray(bind)) {
    throw new Error(`Bind mismatch in SQL: ${sql}. Provided ${bind.length} values.`);
  } else throw e;
}

Prevention

When it happens

Trigger: SQL contains `$3` but bind array has only 2 elements; SQL contains `$x` (non-numeric token) while bind is an array (named tokens require an object).

Common situations: Editing a query and adding a new `?`/`$N` placeholder without extending the bind array; off-by-one when generating SQL dynamically; mixing named and positional syntax in the same query.

Related errors


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