sidorares/node-mysql2 · error · TypeError

Bind parameters must not contain function(s). To pass the…

Error message

Bind parameters must not contain function(s). To pass the body of a function as a string call .toString() first

What it means

In Connection.execute (lib/base/connection.js:801-805), if any bind parameter has typeof === 'function' the driver throws, because serializing a function would silently send its source text — almost never what the developer intended. The error message points to .toString() for the rare case where the function body genuinely is the intended value.

Solutions

  1. Invoke the function: connection.execute(sql, [getTimestamp()]).
  2. If the function's source text truly is the value, call .toString() first: [fn.toString()].
  3. Inspect the params array with Array.isArray + typeof checks before the execute call.

Example fix

// before
connection.execute('UPDATE t SET ts = ?', [Date.now]);

// after
connection.execute('UPDATE t SET ts = ?', [Date.now()]);
Defensive patterns

Strategy: validation

Validate before calling

const assertNoFunctions = (vals) => vals.forEach(v => { if (typeof v === 'function') throw new TypeError(`Bind value is a function: ${v.name}`); });

Type guard

const hasNoFunctions = (vals) => vals.every(v => typeof v !== 'function');

Prevention

When it happens

Trigger: Passing a callback or builder function instead of its result: connection.execute(sql, [getTimestamp]) instead of [getTimestamp()]; spreading an object that contains a method; passing a Validator/Ref where a value is expected.

Common situations: Forgotten invocation parentheses; ORM/query-builder integration that emits function refs; copying a value from a config object that holds setters.

Related errors


AI-assisted analysis of sidorares/node-mysql2@8b1f829d37 (2026-08-11). Data as JSON: /api/errors/a8d38585821be3e2. Report an issue: GitHub.

Appendix: source

Thrown at lib/base/connection.js:802

      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'
          );
        }
      });
    }
    const executeCommand = new Commands.Execute(options, cb);

    const prepareAndExecute = (errorCb) => {
      const prepareCommand = new Commands.Prepare(options, (err, stmt) => {
        if (err) {
          // skip execute command if prepare failed
          executeCommand.start = function () {
            return null;
          };
          errorCb(err);
          executeCommand.emit('end');
          return;
        }

View on GitHub (pinned to 8b1f829d37)