{"record":{"id":"3346a989d5ba48c8","repo":"tursodatabase/turso","slug":"unknown-parameter-name-name","errorCode":null,"errorMessage":"Unknown parameter name: ${name}","messagePattern":"Unknown parameter name: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"bindings/react-native/src/Statement.ts","lineNumber":89,"sourceCode":"    for (let i = 0; i < params.length; i++) {\n      const position = i + 1; // 1-indexed\n      const value = params[i]!;\n\n      this.bindValue(position, value);\n    }\n  }\n\n  /**\n   * Bind named parameters\n   *\n   * @param params - Object with named parameters\n   */\n  private bindNamed(params: Record<string, SQLiteValue>): void {\n    for (const [name, value] of Object.entries(params)) {\n      // Get position for named parameter\n      const position = this._statement.namedPosition(name);\n      if (position < 0) {\n        throw new Error(`Unknown parameter name: ${name}`);\n      }\n\n      this.bindValue(position, value);\n    }\n  }\n\n  /**\n   * Bind a single value at a position\n   *\n   * @param position - 1-indexed position\n   * @param value - Value to bind\n   */\n  private bindValue(position: number, value: SQLiteValue): void {\n    if (value === null || value === undefined) {\n      this._statement.bindPositionalNull(position);\n    } else if (typeof value === 'number') {\n      // Check if integer or float\n      if (Number.isInteger(value)) {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/react-native/src/Statement.ts#L71-L107","documentation":"When bind() receives a single object, bindNamed() iterates its entries and asks the native statement for each parameter's index via namedPosition(). SQLite named parameters carry a :, @, or $ prefix; if the SQL contains no parameter matching the given name (typo, extra key, or prefix-form mismatch), namedPosition returns a negative value and the binding throws 'Unknown parameter name'. The whole bind is rejected before any value is bound.","triggerScenarios":"`stmt.bind({ id: 1 })` where the SQL is 'SELECT * FROM t WHERE id = :userId' (id vs userId); passing an options object with extraneous keys alongside the real parameters; SQL rewritten to rename or remove a parameter while caller code still passes the old key; prefix conventions mixed (':name' in SQL but '@name' passed, where matching is prefix-sensitive).","commonSituations":"Passing a row object plus metadata keys (e.g., reusing a request body as bind params); renaming SQL parameters during a refactor; building dynamic WHERE clauses where the parameter set and the object keys drift; copy-pasting SQL from one query to another with different parameter names.","solutions":["Make every object key match a named parameter in the SQL text exactly (watch the :, @, $ prefix form on both sides)","Strip extraneous keys before binding — bind only the parameters the statement actually declares","Centralize parameter names as constants shared by the SQL template and the bind object so they cannot drift"],"exampleFix":"// before\nconst stmt = conn.prepare('SELECT * FROM users WHERE id = :userId');\nstmt.bind({ id: 42 }); // throws: Unknown parameter name: id\n\n// after\nconst stmt = conn.prepare('SELECT * FROM users WHERE id = :userId');\nstmt.bind({ userId: 42 });","handlingStrategy":"validation","validationCode":"// Validate keys against the SQL's own parameter names before binding\nfunction namedParamsOf(sql: string): Set<string> {\n  return new Set(\n    (sql.match(/[:@$][A-Za-z_][\\w$]*/g) ?? []).map((p) => p.replace(/^[:@$]/, ''))\n  );\n}\n\nfunction pickBindObject(sql: string, obj: Record<string, SQLiteValue>) {\n  const known = namedParamsOf(sql);\n  const out: Record<string, SQLiteValue> = {};\n  for (const [k, v] of Object.entries(obj)) {\n    if (known.has(k.replace(/^[:@$]/, ''))) out[k] = v;\n  }\n  return out; // extraneous keys dropped, typos become 'missing param' which is easier to spot\n}","typeGuard":null,"tryCatchPattern":"try { stmt.bind(params); } catch (e) { if (e instanceof Error && /Unknown parameter name/.test(e.message)) { throw new Error(`${e.message} — SQL expects one of: ${[...namedParamsOf(sql)]}`); } throw e; }","preventionTips":["Share parameter-name constants between the SQL template and the bind object","Never pass raw request bodies as bind objects — pick known keys first","Match the :, @, $ prefix convention consistently between SQL and keys"],"tags":["react-native","statement","bind","named-parameters","sql"],"backgroundTag":"parameter-binding-mismatch","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}