{"record":{"id":"1690752637457ea0","repo":"tursodatabase/turso","slug":"no-connection-available","errorCode":null,"errorMessage":"No connection available","messagePattern":"No connection available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"bindings/react-native/src/Database.ts","lineNumber":228,"sourceCode":"    const operation = this._nativeSyncDb.create();\n    await driveVoidOperation(operation, this._nativeSyncDb, this._ioContext);\n\n    // Get connection\n    const connOperation = this._nativeSyncDb.connect();\n    this._connection = await driveConnectionOperation(connOperation, this._nativeSyncDb, this._ioContext);\n  }\n\n  /**\n   * Prepare a SQL statement\n   *\n   * @param sql - SQL statement to prepare\n   * @returns Prepared statement\n   */\n  prepare(sql: string): Statement {\n    this.checkOpen();\n\n    if (!this._connection) {\n      throw new Error('No connection available');\n    }\n\n    const nativeStmt = this._connection.prepareSingle(sql);\n    return new Statement(nativeStmt, this._connection!, this._execLock, this._extraIo);\n  }\n\n  /**\n   * Execute SQL without returning results (for DDL, multi-statement SQL)\n   *\n   * @param sql - SQL to execute\n   */\n  async exec(sql: string): Promise<void> {\n    this.checkOpen();\n\n    if (!this._connection) {\n      throw new Error('No connection available');\n    }\n","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/react-native/src/Database.ts#L210-L246","documentation":"prepare() calls checkOpen() and then defensively re-checks that this._connection is set before invoking _connection.prepareSingle(sql). The connection object is created during connect() (from the native database's connect() call). This guard fires when the Database instance believes it is initialized but the native connection handle is absent — normally an internal invariant or a race with close(), since checkOpen() would otherwise throw 'Database not connected' first.","triggerScenarios":"Calling db.prepare(sql) in a narrow window while close() is tearing the instance down (connection closed before _closed is set), or on a Database constructed but whose connect() partially failed after setting _connected. In normal flows checkOpen() catches the not-connected case first, so seeing this exact message usually means concurrent close/prepare interleaving.","commonSituations":"Component unmount racing a query: an effect starts `db.prepare(...)` while a cleanup handler already called db.close(); React 18 StrictMode double-mount/double-unmount; sharing one Database instance across screens and closing it from one while another still prepares statements.","solutions":["Serialize close vs. use: await all outstanding queries before calling db.close(), and gate new calls on `db.open`","Check `db.open` (returns !_closed && _connection !== null) before preparing in UI code that can race unmount","Give each long-lived consumer its own Database instance instead of sharing one closable instance across screens","If you see it without any close() call, report it as a binding bug — _connected true with _connection null is an internal invariant violation"],"exampleFix":"// before: unmount closes the db while a render-scheduled prepare still runs\nuseEffect(() => {\n  const stmt = db.prepare('SELECT * FROM users'); // may race close()\n  return () => db.close();\n}, []);\n\n// after: guard with the `open` getter and close only after pending work\nuseEffect(() => {\n  if (!db.open) return;\n  const stmt = db.prepare('SELECT * FROM users');\n  // ...\n}, []);\n// elsewhere: await pendingQueries; db.close();","handlingStrategy":"validation","validationCode":"if (!db.open) {\n  throw new Error('Database is not open — connect() first and close() only after all queries finish');\n}\nconst stmt = db.prepare('SELECT * FROM users');","typeGuard":"function isUsableDatabase(db: Database): boolean {\n  return db.open; // `open` getter: !_closed && _connection !== null\n}","tryCatchPattern":"try {\n  const stmt = db.prepare(sql);\n} catch (e) {\n  if (e instanceof Error && /closed|not connected|No connection/.test(e.message)) {\n    await reopenDatabase(); // re-create + connect, then retry once\n    return db.prepare(sql);\n  }\n  throw e;\n}","preventionTips":["Own one Database per long-lived consumer instead of sharing a closable instance across screens","Await all in-flight queries before close() and set db references to null afterwards","Check db.open before statement creation in code that can race unmount/teardown"],"tags":["react-native","connection","lifecycle","race-condition"],"backgroundTag":"connection-not-initialized","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}