sidorares/node-mysql2 · error · TypeError
Bind parameters must be array if namedPlaceholders parameter
Error message
Bind parameters must be array if namedPlaceholders parameter is not enabled
What it means
In Connection.execute(), after named-placeholder resolution, the bind values are required to be an array. If `options.values` is not an array (e.g. a plain object) and `namedPlaceholders` is not enabled in the connection config, mysql2 throws because it cannot map an object's keys to `?` placeholders. Named-placeholder support must be explicitly opted into via the `namedPlaceholders: true` config.
Source
Thrown at lib/base/connection.js:777
} else {
options.values = options.values || values;
}
} else if (typeof values === 'function') {
// execute(sql, cb)
cb = values;
options.sql = sql;
options.values = undefined;
} else {
// execute(sql, values, cb)
options.sql = sql;
options.values = values;
}
this._resolveNamedPlaceholders(options);
// check for values containing undefined
if (options.values) {
//If namedPlaceholder is not enabled and object is passed as bind parameters
if (!Array.isArray(options.values)) {
throw new TypeError(
'Bind parameters must be array if namedPlaceholders parameter is not enabled'
);
}
options.values.forEach((val) => {
//If namedPlaceholder is not enabled and object is passed as bind parameters
if (!Array.isArray(options.values)) {
throw new TypeError(
'Bind parameters must be array if namedPlaceholders parameter is not enabled'
);
}
if (val === undefined) {
throw new TypeError(
'Bind parameters must not contain undefined. To pass SQL NULL specify JS null'
);
}
if (typeof val === 'function') {
throw new TypeError(
'Bind parameters must not contain function(s). To pass the body of a function as a string call .toString() first'View on GitHub (pinned to 5ebe8903d6)
Solutions
- Pass bind parameters as an array: `connection.execute(sql, [1, 2])`.
- Or enable named placeholders in config: `mysql.createConnection({ ..., namedPlaceholders: true })` and use `:name` placeholders in SQL.
Example fix
// before
connection.execute('SELECT * FROM t WHERE a = ? AND b = ?', { a: 1, b: 2 });
// after — option A: array
connection.execute('SELECT * FROM t WHERE a = ? AND b = ?', [1, 2]);
// after — option B: enable named placeholders
mysql.createConnection({ host, namedPlaceholders: true });
connection.execute('SELECT * FROM t WHERE a = :a AND b = :b', { a: 1, b: 2 }); Defensive patterns
Strategy: validation
Validate before calling
function normalizeParams(values, namedPlaceholders) {
if (values != null && !Array.isArray(values)) {
if (!namedPlaceholders) {
throw new TypeError('Pass an array, or enable namedPlaceholders: true');
}
}
return values;
}
// usage:
const v = normalizeParams(values, conn.config.namedPlaceholders);
conn.execute(sql, v); Type guard
function isBindableArray(values) {
return Array.isArray(values);
} Prevention
- Standardise on arrays for `?` placeholders across the codebase.
- Enable namedPlaceholders explicitly if you want object params.
- Lint for object literals passed as the second arg to execute/query.
When it happens
Trigger: Calling `connection.execute('SELECT * FROM t WHERE a = ? AND b = ?', { a: 1, b: 2 })` (passing an object) without `namedPlaceholders: true`. Or passing an object to `.query()`/`.execute()` values when the config flag is off. Also triggered by accidentally passing a single non-array argument where an array of bind values is expected.
Common situations: Developer assumes object-style parameters work by default (they do in some ORMs); copy-pasting query syntax from a library that uses named params; forgetting to set `namedPlaceholders: true` when migrating from another driver.
Related errors
- Bind parameters must not contain undefined. To pass SQL NULL
- Bind parameters must not contain function(s). To pass the bo
- Bind parameters must not contain undefined
- You have tried to call .then(), .catch(), or invoked await o
AI-assisted analysis of sidorares/node-mysql2@5ebe8903d6 (2026-08-03).
Data as JSON: /data/errors/3bf99159891e2645.json.
Report an issue: GitHub.