{"record":{"id":"377c7aba5e461e6c","repo":"sidorares/node-mysql2","slug":"callback-function-is-not-available-with-promise-cl-377c7a","errorCode":null,"errorMessage":"Callback function is not available with promise clients.","messagePattern":"Callback function is not available with promise clients\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/promise/pool.js","lineNumber":42,"sourceCode":"      corePool.getConnection((err, coreConnection) => {\n        if (err) {\n          reject(err);\n        } else {\n          resolve(new PromisePoolConnection(coreConnection, this.Promise));\n        }\n      });\n    });\n  }\n\n  releaseConnection(connection) {\n    if (connection instanceof PromisePoolConnection) connection.release();\n  }\n\n  query(sql, args) {\n    const corePool = this.pool;\n    const stackHolder = captureStackHolder(PromisePool.prototype.query);\n    if (typeof args === 'function') {\n      throw new Error(\n        'Callback function is not available with promise clients.'\n      );\n    }\n    return new this.Promise((resolve, reject) => {\n      const done = makeDoneCb(resolve, reject, stackHolder);\n      if (args !== undefined) {\n        corePool.query(sql, args, done);\n      } else {\n        corePool.query(sql, done);\n      }\n    });\n  }\n\n  execute(sql, args) {\n    const corePool = this.pool;\n    const stackHolder = captureStackHolder(PromisePool.prototype.execute);\n    if (typeof args === 'function') {\n      throw new Error(","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/sidorares/node-mysql2/blob/8b1f829d3706404ab372cf97bd77ebcf86578d97/lib/promise/pool.js#L24-L60","documentation":"PromisePool.query() (pool.query from mysql2/promise) throws synchronously when args is a function. Pools in the promise API return a promise per query and cannot invoke a callback; passing one indicates the caller mixed the two APIs. Common because pools are often shared and one branch of code may still be callback-based.","triggerScenarios":"const pool = createPool({...}); pool.query('SELECT 1', (err, rows) => {...}) where createPool came from 'mysql2/promise'.","commonSituations":"Shared pool across a codebase mid-migration; generic db helpers (db.query(sql, cb)) that were not updated; sample code copied from the callback docs.","solutions":["Await the result: const [rows] = await pool.query(sql).","Use the callback pool (require('mysql2').createPool) for callback-style code.","Search the codebase for `.query(.*, (` to find stray callbacks on promise pools."],"exampleFix":"// before\nconst pool = createPool({ host: 'localhost' });\npool.query('SELECT 1', (err, rows) => { /* ... */ });\n// after\nconst pool = createPool({ host: 'localhost' });\nconst [rows] = await pool.query('SELECT 1');","handlingStrategy":"type-guard","validationCode":"if (typeof args === 'function') {\n  throw new TypeError('pool.query() in the promise API does not accept a callback; use await');\n}","typeGuard":"function isPromisePool(p) {\n  return p != null && 'Promise' in p && 'pool' in p;\n}","tryCatchPattern":"try {\n  const [rows] = await pool.query(sql, args);\n} catch (err) {\n  if (/Callback function is not available/.test(err.message)) {\n    // strip the callback and re-run as promise\n  } else {\n    throw err;\n  }\n}","preventionTips":["Standardize on the promise pool across the codebase to avoid mixed-API helpers.","Search shared db helpers for callback parameters and update them to async.","Import pools from a single module so the API choice is consistent."],"tags":["promise-api","callback","api-misuse","pool","migration"],"backgroundTag":null,"analyzedSha":"8b1f829d3706404ab372cf97bd77ebcf86578d97","analyzedAt":"2026-08-11T02:54:28.964Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}