{"record":{"id":"2adfbaff897e232e","repo":"sidorares/node-mysql2","slug":"callback-function-is-not-available-with-promise-cl","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/connection.js","lineNumber":35,"sourceCode":"    this.Promise = promiseImpl || Promise;\n    inheritEvents(connection, this, [\n      'error',\n      'drain',\n      'connect',\n      'end',\n      'enqueue',\n    ]);\n  }\n\n  release() {\n    this.connection.release();\n  }\n\n  query(query, params) {\n    const c = this.connection;\n    const stackHolder = captureStackHolder(PromiseConnection.prototype.query);\n    if (typeof params === '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 (params !== undefined) {\n        c.query(query, params, done);\n      } else {\n        c.query(query, done);\n      }\n    });\n  }\n\n  execute(query, params) {\n    const c = this.connection;\n    const stackHolder = captureStackHolder(PromiseConnection.prototype.execute);\n    if (typeof params === 'function') {\n      throw new Error(","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/sidorares/node-mysql2/blob/8b1f829d3706404ab372cf97bd77ebcf86578d97/lib/promise/connection.js#L17-L53","documentation":"PromiseConnection.query() (the wrapper returned by connection.promise() and by mysql2/promise) detects a function passed as the second argument — the legacy callback position of the callback API — and throws synchronously. The promise API intentionally rejects the callback pattern: use await (and the returned promise) or use the callback API, never both on the same client. Because this is a synchronous throw (not a rejected promise), it propagates immediately unless the call is inside try/catch or an async function.","triggerScenarios":"Calling conn.query(sql, cb) on a connection obtained via .promise() or imported from 'mysql2/promise'. Example: const conn = (await createConnection({})).promise(); conn.query('SELECT 1', (err, rows) => {...}).","commonSituations":"Migrating from the callback API to the promise API and leaving a callback in place; copy-pasting a callback-style snippet into a file that imports from 'mysql2/promise'; refactoring a helper that still passes a callback through.","solutions":["Drop the callback and await the result: const [rows] = await conn.query(sql).","If you must use callbacks, import from 'mysql2' (callback API) instead of 'mysql2/promise', or use the unwrapped connection.","Wrap the call in try/catch (or an async function with await) so the synchronous throw becomes a catchable rejection."],"exampleFix":"// before\nconst conn = await createConnection({ host: 'localhost' });\nconn.query('SELECT 1', (err, rows) => { if (err) throw err; console.log(rows); });\n// after\nconst conn = await createConnection({ host: 'localhost' });\nconst [rows] = await conn.query('SELECT 1');\nconsole.log(rows);","handlingStrategy":"type-guard","validationCode":"function isThenable(v) {\n  return v != null && typeof v.then === 'function';\n}\n\n// ensure you never pass a function as the 2nd arg to a promise query\nif (typeof params === 'function') {\n  throw new TypeError('Pass a callback to the callback API, not the promise API');\n}","typeGuard":"function isPromiseConnection(c) {\n  // promise clients expose a `.Promise` property and lack the callback-style internals\n  return c != null && 'Promise' in c && typeof c.query === 'function' && c.query.length < 3;\n}","tryCatchPattern":"try {\n  const [rows] = await conn.query(sql, params);\n} catch (err) {\n  if (/Callback function is not available/.test(err.message)) {\n    // caller mixed APIs: re-issue without the callback\n  } else {\n    throw err;\n  }\n}","preventionTips":["Pick one API per module: import from 'mysql2' (callback) or 'mysql2/promise' (promise), not both.","During migration, grep for `.query\\(.*, \\(` and `.execute\\(.*, \\(` to find stray callbacks.","Lint against passing function-typed args into promise client methods."],"tags":["promise-api","callback","api-misuse","migration"],"backgroundTag":null,"analyzedSha":"8b1f829d3706404ab372cf97bd77ebcf86578d97","analyzedAt":"2026-08-11T02:54:28.964Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}