{"record":{"id":"637035d493e16839","repo":"tursodatabase/turso","slug":"failed-to-get-column-name-at-index-i","errorCode":null,"errorMessage":"Failed to get column name at index ${i}","messagePattern":"Failed to get column name at index (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"bindings/react-native/src/Statement.ts","lineNumber":340,"sourceCode":"      if (this._execLock) {\n        this._execLock.release();\n      }\n    }\n  }\n\n  /**\n   * Read current row into an object\n   *\n   * @returns Row object with column name keys\n   */\n  private readRow(): Row {\n    const row: Row = {};\n    const columnCount = this._statement.columnCount();\n\n    for (let i = 0; i < columnCount; i++) {\n      const name = this._statement.columnName(i);\n      if (!name) {\n        throw new Error(`Failed to get column name at index ${i}`);\n      }\n\n      const value = this.readColumnValue(i);\n      row[name] = value;\n    }\n\n    return row;\n  }\n\n  /**\n   * Read value at column index\n   *\n   * @param index - Column index\n   * @returns Column value\n   */\n  private readColumnValue(index: number): SQLiteValue {\n    const kind = this._statement.rowValueKind(index);\n","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/react-native/src/Statement.ts#L322-L358","documentation":"Statement.readRow() iterates from 0 to columnCount()-1 calling the native columnName(i); a falsy (null or empty) name at any index throws with that index. The count and names come from the native JSI host object, so for a valid prepared SELECT this should be impossible — hitting it means the JSI metadata layer is not returning what the JS side expects.","triggerScenarios":"JS package and native binary built from different revisions (columnName returning undefined for an index the JS columnCount trusts); the statement being finalized concurrently between the columnCount() call and the name-read loop; a native build where the host object was not registered correctly.","commonSituations":"Upgrading @tursodatabase/sync-react-native in package.json without rebuilding pods/gradle artifacts; stale Metro cache serving old JS against a new native module; CI builds with cached native artifacts; Expo prebuild caches.","solutions":["Fully rebuild the native module: cd ios && pod install (or pod deintegrate && pod install) and a clean Android build (./gradlew clean)","Reset Metro caches: npx react-native start --reset-cache","Pin the npm package and the native pod/package to matching versions","Ensure no code path finalizes the statement or closes the database while a get() row read is in flight"],"exampleFix":"# before\nnpm install @tursodatabase/sync-react-native@latest\n# app throws: Failed to get column name at index 3\n\n# after\ncd ios && pod deintegrate && pod install && cd ..\ncd android && ./gradlew clean && cd ..\nnpx react-native start --reset-cache","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isColumnNameError(e: unknown): boolean {\n  return e instanceof Error && /Failed to get column name at index \\d+/.test(e.message);\n}","tryCatchPattern":"try {\n  const row = await stmt.get(id);\n} catch (e) {\n  if (isColumnNameError(e)) {\n    // binding/native skew: rebuild native + reset Metro, then retry once\n    throw new Error('Native/JS binding mismatch — run pod install / gradlew clean and --reset-cache');\n  }\n  throw e;\n}","preventionTips":["Upgrade the npm package and native module together, always followed by pod install / clean gradle build","Reset Metro cache after SDK upgrades","Pin matching JS and native versions in lockfiles","Never close the database while a row read is in flight"],"tags":["column-metadata","version-skew","jsi","react-native"],"backgroundTag":"invalid-column-index","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}