tursodatabase/turso · error · Error

sync is disabled as database was opened without sync support

Error message

sync is disabled as database was opened without sync support

What it means

The sync-flavored Database only builds a SyncEngine when constructed with a URL; when opts.url is null it wraps a plain local database and sets #engine = null. pull() guards on that engine and throws this error, telling you the instance has no sync capability. pull() (long-poll wait + apply) simply does not exist for local-only databases.

Source

Thrown at bindings/javascript/sync/packages/native/promise.ts:175

     */
    override async connect() {
        if (this.connected) {
            return;
        } else if (this.#engine == null) {
            await super.connect();
        } else {
            await run(this.#runner!, this.#engine.connect());
        }
        this.connected = true;
    }
    /**
     * pull new changes from the remote database
     * if {@link DatabaseOpts.longPollTimeoutMs} is set - then server will hold the connection open until either new changes will appear in the database or timeout occurs.
     * @returns true if new changes were pulled from the remote
     */
    async pull() {
        if (this.#engine == null) {
            throw new Error("sync is disabled as database was opened without sync support")
        }
        const changes = await this.#guards!.wait(async () => await run(this.#runner!, this.#engine.wait()));
        if (changes.empty()) {
            return false;
        }
        await this.#guards!.apply(async () => await run(this.#runner!, this.#engine.apply(changes)));
        return true;
    }
    /**
     * push new local changes to the remote database
     * if {@link DatabaseOpts.transform} is set - then provided callback will be called for every mutation before sending it to the remote
     */
    async push() {
        if (this.#engine == null) {
            throw new Error("sync is disabled as database was opened without sync support")
        }
        await this.#guards!.push(async () => await run(this.#runner!, this.#engine.push()));
    }

View on GitHub (pinned to bad083fafb)

Solutions

  1. Pass url (and usually authToken) in DatabaseOpts to enable the sync engine: new Database({ path, url: 'libsql://...', authToken }).
  2. If this instance is intentionally local-only, do not call pull() — use the plain native package instead.
  3. Guard calls with a sync-enabled flag captured at construction time.

Example fix

// before
const db = new Database({ path: 'local.db' }); // no url -> engine disabled
await db.pull(); // throws

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

Strategy: type-guard

Validate before calling

// capture sync capability at construction time
const syncEnabled = opts.url != null;
const db = new Database(opts);
if (syncEnabled) { await db.connect(); await db.pull(); }

Type guard

function isSyncCapable(db: Database): boolean {
  // engine is private; rely on your own construction flag instead
  return db instanceof Database && (db as any).pull === 'function' && syncEnabledFlag(db);
}

Prevention

When it happens

Trigger: new Database({ path: 'local.db' }) from the sync package (no url option) followed by db.pull(); a url option that is undefined because the env var was missing; shared factory code that sometimes passes a URL and sometimes does not.

Common situations: One code path used for both local-only and synced deployments where the sync URL env var is absent locally or in CI; optional sync feature toggled by presence of a URL; tests constructing the DB without a remote.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/7bdb25a52cf28ba9. Report an issue: GitHub.