{"record":{"id":"e3b2d6c2a1416065","repo":"tursodatabase/turso","slug":"pull-is-only-available-for-sync-databases","errorCode":null,"errorMessage":"pull() is only available for sync databases","messagePattern":"pull\\(\\) is only available for sync databases","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"bindings/react-native/src/Database.ts","lineNumber":362,"sourceCode":"   * Push local changes to remote (sync databases only)\n   */\n  async push(): Promise<void> {\n    if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {\n      throw new Error('push() is only available for sync databases');\n    }\n\n    const operation = this._nativeSyncDb.pushChanges();\n    await driveVoidOperation(operation, this._nativeSyncDb, this._ioContext);\n  }\n\n  /**\n   * Pull remote changes and apply locally (sync databases only)\n   *\n   * @returns true if changes were applied, false if no changes\n   */\n  async pull(): Promise<boolean> {\n    if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {\n      throw new Error('pull() is only available for sync databases');\n    }\n\n    // Wait for changes\n    const waitOperation = this._nativeSyncDb.waitChanges();\n    const changes = await driveChangesOperation(waitOperation, this._nativeSyncDb, this._ioContext);\n\n    // If no changes, return false\n    if (!changes) {\n      return false;\n    }\n\n    // Apply changes\n    const applyOperation = this._nativeSyncDb.applyChanges(changes);\n    await driveVoidOperation(applyOperation, this._nativeSyncDb, this._ioContext);\n\n    return true;\n  }\n","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/react-native/src/Database.ts#L344-L380","documentation":"pull() waits for remote changes via the native sync engine (waitChanges) and applies them, which only exists for sync databases. The guard requires _isSync, _nativeSyncDb, and _ioContext — all created during connect() when the Database was constructed with a `url`. A local-only database has no sync engine, so pull is meaningless and rejected up front.","triggerScenarios":"Calling await db.pull() on a Database constructed without `url`; calling it on a sync database before `await db.connect()` finished creating the native sync handle and IO context; the url option resolving to null at construction time (url function returning null).","commonSituations":"Feature-flagged sync where some builds construct the db local-only but shared code still calls pull(); forgetting to await connect() before an initial pull; copying example code for pull() into the local-only quick-start snippet from the README.","solutions":["Pass url and authToken in the Database options so isSyncConfig() selects the sync path","Always `await db.connect()` before pull() — it bootstraps the replica and creates the sync handle","Gate sync calls: `if (db.isSync) await db.pull();` in code paths shared with local-only builds","Verify a url function option actually returns a string, not null"],"exampleFix":"// before\nconst db = new Database({ path: getDbPath('notes.db') });\nawait db.connect();\nawait db.pull(); // throws\n\n// after\nconst db = new Database({\n  path: getDbPath('notes.db'),\n  url: () => remoteUrl, // string or function returning string\n  authToken,\n});\nawait db.connect();\nif (db.isSync) {\n  await db.pull();\n}","handlingStrategy":"type-guard","validationCode":"if (!db.isSync) {\n  return; // local-only build: nothing to pull\n}\nawait db.pull();","typeGuard":"function canPull(db: Database): boolean {\n  return db.isSync && db.open;\n}","tryCatchPattern":"try {\n  const changed = await db.pull();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('only available for sync databases')) {\n    return; // configuration mismatch — skip sync on local-only instances\n  }\n  throw e;\n}","preventionTips":["Feature-flag sync calls behind db.isSync rather than try/catching the misuse error","Ensure the url option (string or function) resolves to a real string before constructing","Await connect() first; it creates the sync handle and IO context that pull() requires"],"tags":["react-native","sync","api-misuse","embedded-replicas"],"backgroundTag":"sync-mode-required","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}