{"record":{"id":"a8d38585821be3e2","repo":"sidorares/node-mysql2","slug":"bind-parameters-must-not-contain-function-s-to-p","errorCode":null,"errorMessage":"Bind parameters must not contain function(s). To pass the body of a function as a string call .toString() first","messagePattern":"Bind parameters must not contain function\\(s\\)\\. To pass the body of a function as a string call \\.toString\\(\\) first","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/base/connection.js","lineNumber":802,"sourceCode":"      if (!Array.isArray(options.values)) {\n        throw new TypeError(\n          'Bind parameters must be array if namedPlaceholders parameter is not enabled'\n        );\n      }\n      options.values.forEach((val) => {\n        //If namedPlaceholder is not enabled and object is passed as bind parameters\n        if (!Array.isArray(options.values)) {\n          throw new TypeError(\n            'Bind parameters must be array if namedPlaceholders parameter is not enabled'\n          );\n        }\n        if (val === undefined) {\n          throw new TypeError(\n            'Bind parameters must not contain undefined. To pass SQL NULL specify JS null'\n          );\n        }\n        if (typeof val === 'function') {\n          throw new TypeError(\n            'Bind parameters must not contain function(s). To pass the body of a function as a string call .toString() first'\n          );\n        }\n      });\n    }\n    const executeCommand = new Commands.Execute(options, cb);\n\n    const prepareAndExecute = (errorCb) => {\n      const prepareCommand = new Commands.Prepare(options, (err, stmt) => {\n        if (err) {\n          // skip execute command if prepare failed\n          executeCommand.start = function () {\n            return null;\n          };\n          errorCb(err);\n          executeCommand.emit('end');\n          return;\n        }","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/sidorares/node-mysql2/blob/8b1f829d3706404ab372cf97bd77ebcf86578d97/lib/base/connection.js#L784-L820","documentation":"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.","triggerScenarios":"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.","commonSituations":"Forgotten invocation parentheses; ORM/query-builder integration that emits function refs; copying a value from a config object that holds setters.","solutions":["Invoke the function: connection.execute(sql, [getTimestamp()]).","If the function's source text truly is the value, call .toString() first: [fn.toString()].","Inspect the params array with Array.isArray + typeof checks before the execute call."],"exampleFix":"// before\nconnection.execute('UPDATE t SET ts = ?', [Date.now]);\n\n// after\nconnection.execute('UPDATE t SET ts = ?', [Date.now()]);","handlingStrategy":"validation","validationCode":"const assertNoFunctions = (vals) => vals.forEach(v => { if (typeof v === 'function') throw new TypeError(`Bind value is a function: ${v.name}`); });","typeGuard":"const hasNoFunctions = (vals) => vals.every(v => typeof v !== 'function');","tryCatchPattern":null,"preventionTips":["Audit query-helper callsites that accept builder functions.","Enable @typescript-eslint/no-misused-promises and strict param typing."],"tags":["prepared-statements","bind-parameters","api-usage","validation"],"backgroundTag":null,"analyzedSha":"8b1f829d3706404ab372cf97bd77ebcf86578d97","analyzedAt":"2026-08-11T02:54:28.964Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}