tursodatabase/turso · error

push() is only available for sync databases

Error message

push() is only available for sync databases

What it means

push() requires a sync-mode database: _isSync true, a native sync database handle (_nativeSyncDb, created by initSyncDatabase when the `url` option is present), and an _ioContext for driving the native operation loop. If the Database was constructed without a url it is local-only and has no remote to push to, so the call is rejected before touching the network.

Solutions

  1. Construct the database with sync options: new Database({ path: getDbPath('app.db'), url: 'libsql://...turso.io', authToken })
  2. Await db.connect() before calling push() so the sync handle and IO context exist
  3. Guard the call with the `db.isSync` getter (or track it yourself) in code shared between local and sync deployments
  4. Check the option spelling — only `url` (string or function returning a string) enables sync mode

Example fix

// before
const db = new Database({ path: getDbPath('app.db') });
await db.connect();
await db.push(); // throws: local-only database

// after
const db = new Database({
  path: getDbPath('app.db'),
  url: 'libsql://my-db.turso.io',
  authToken: token,
});
await db.connect();
await db.push();
Defensive patterns

Strategy: type-guard

Validate before calling

if (!db.isSync) {
  throw new Error('push() called on a local-only database — construct Database with url + authToken');
}
await db.push();

Type guard

function isSyncDatabase(db: Database): boolean {
  return db.isSync; // true only when constructed with a `url` option
}

Try / catch

try {
  await db.push();
} catch (e) {
  if (e instanceof Error && e.message.includes('only available for sync databases')) {
    // Configuration bug, not transient: fix construction; do not retry
    throw new Error('Misconfigured Database: add url/authToken options to enable sync');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling await db.push() on a Database created with only `{ path }` (local-only), or on a sync-configured database before connect() has created _nativeSyncDb/_ioContext. Also when a typo'd option key (e.g. `urls:` instead of `url:`) silently makes isSyncConfig() return false.

Common situations: Starting a project local-only then adding sync calls without updating the Database constructor; development builds pointing at a config object where url is conditionally undefined; calling push() before awaiting db.connect().

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/f21b4c22ec341e15. Report an issue: GitHub.

Appendix: source

Thrown at bindings/react-native/src/Database.ts:348

  async transaction<T>(fn: () => T | Promise<T>): Promise<T> {
    this.checkOpen();
    await this.exec('BEGIN');
    try {
      const result = await fn();
      await this.exec('COMMIT');
      return result;
    } catch (error) {
      await this.exec('ROLLBACK');
      throw error;
    }
  }

  /**
   * Push local changes to remote (sync databases only)
   */
  async push(): Promise<void> {
    if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {
      throw new Error('push() is only available for sync databases');
    }

    const operation = this._nativeSyncDb.pushChanges();
    await driveVoidOperation(operation, this._nativeSyncDb, this._ioContext);
  }

  /**
   * Pull remote changes and apply locally (sync databases only)
   *
   * @returns true if changes were applied, false if no changes
   */
  async pull(): Promise<boolean> {
    if (!this._isSync || !this._nativeSyncDb || !this._ioContext) {
      throw new Error('pull() is only available for sync databases');
    }

    // Wait for changes
    const waitOperation = this._nativeSyncDb.waitChanges();

View on GitHub (pinned to 244cde92a7)