{"id":"642f93972a9cf502","repo":"sequelize/sequelize","slug":"sequelize-rawquery-requires-a-string-as-the-first","errorCode":null,"errorMessage":"Sequelize#rawQuery requires a string as the first parameter.","messagePattern":"Sequelize#rawQuery requires a string as the first parameter\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/sequelize.js","lineNumber":255,"sourceCode":"        '\"sql\" cannot be an object. Pass a string instead, and pass bind and replacement parameters through the \"options\" parameter',\n      );\n    }\n\n    sql = sql.trim();\n\n    if (options.replacements) {\n      sql = injectReplacements(sql, this.dialect, options.replacements);\n    }\n\n    // queryRaw will throw if 'replacements' is specified, as a way to warn users that they are miusing the method.\n    delete options.replacements;\n\n    return this.queryRaw(sql, options);\n  }\n\n  async queryRaw(sql, options) {\n    if (typeof sql !== 'string') {\n      throw new TypeError('Sequelize#rawQuery requires a string as the first parameter.');\n    }\n\n    if (options != null && 'replacements' in options) {\n      throw new TypeError(`Sequelize#rawQuery does not accept the \"replacements\" options.\nOnly bind parameters can be provided, in the dialect-specific syntax.\nUse Sequelize#query if you wish to use replacements.`);\n    }\n\n    options = { ...this.options.query, ...options, bindParameterOrder: null };\n\n    let bindParameters;\n    if (options.bind != null) {\n      const isBindArray = Array.isArray(options.bind);\n      if (!isPlainObject(options.bind) && !isBindArray) {\n        throw new TypeError(\n          'options.bind must be either a plain object (for named parameters) or an array (for numeric parameters)',\n        );\n      }","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/sequelize/sequelize/blob/7e1deec499d5afbb8d1877c2f4d545cead1214ec/packages/core/src/sequelize.js#L237-L273","documentation":"queryRaw is the low-level variant of query that does *not* process replacements. It requires the first parameter to be a string so the dialect's bind-parameter mapper can scan it. Line 254 throws TypeError on any non-string input, catching mistakes where users route a sql expression or options object through queryRaw.","triggerScenarios":"Calling `sequelize.queryRaw(someObject)`, `sequelize.queryRaw(number)`, or passing a BaseSqlExpression that should have gone through `query()` instead.","commonSituations":"Refactoring and accidentally switching a `query` call to `queryRaw` while still passing an expression; calling queryRaw on user input that was not coerced to a string.","solutions":["Ensure the first argument is a string literal or template: `sequelize.queryRaw('SELECT $1', { bind: [1] })`.","If you have a sql`` expression, use `sequelize.query()` instead — it will format the BaseSqlExpression for you.","Coerce/validate dynamic SQL to a string before calling queryRaw."],"exampleFix":"// before\nawait sequelize.queryRaw(sql`SELECT ${1}`); // sql expression is not a string\n\n// after\nawait sequelize.query(sql`SELECT ${1}`); // use query() for sql expressions\n// or:\nawait sequelize.queryRaw('SELECT $1', { bind: [1] });","handlingStrategy":"type-guard","validationCode":"function assertRawSqlString(sql) {\n  if (typeof sql !== 'string') {\n    throw new TypeError('queryRaw requires a string; for sql expressions use query() instead.');\n  }\n  return sql;\n}\nawait sequelize.queryRaw(assertRawSqlString(sql), { bind });","typeGuard":"function isRawQueryString(sql) {\n  return typeof sql === 'string';\n}","tryCatchPattern":"try {\n  await sequelize.queryRaw(expr, { bind });\n} catch (e) {\n  if (/requires a string as the first parameter/.test(e.message)) {\n    await sequelize.query(expr, { bind });\n  } else throw e;\n}","preventionTips":["Reserve queryRaw for plain-string SQL only; route sql`` expressions through query().","Add a lint rule discouraging queryRaw with non-string first args.","Document in code comments when queryRaw is chosen over query and why."],"tags":["queryraw","query","argument-validation"],"analyzedSha":"7e1deec499d5afbb8d1877c2f4d545cead1214ec","analyzedAt":"2026-08-03T18:58:44.549Z","schemaVersion":2}