tursodatabase/turso · error · Error
Statement execution failed with status: ${result.status}
Error message
Statement execution failed with status: ${result.status} What it means
Inside rawRun()'s executeWithIo loop, TursoStatus.IO (3) is handled by draining sync-engine IO, and any status other than TursoStatus.DONE (1) is rejected with its numeric code. The number maps to the TursoStatus enum in types.ts: 4=BUSY, 5=INTERRUPT, 127=ERROR, 128=MISUSE, 129=CONSTRAINT, 130=READONLY, 131=DATABASE_FULL, 132=NOTADB, 133=CORRUPT, 134=IOERR. The message is a raw number, so decoding it against the enum is the first diagnostic step.
Source
Thrown at bindings/react-native/src/Statement.ts:199
*/
private async executeWithIo(): Promise<{ status: number; rowsChanged: number }> {
while (true) {
const result = this._statement.execute();
if (result.status === TursoStatus.IO) {
// Statement needs IO (e.g., loading missing pages with partial sync)
this._statement.runIo();
// Drain sync engine IO queue
if (this._extraIo) {
await this._extraIo();
}
continue;
}
if (result.status !== TursoStatus.DONE) {
throw new Error(`Statement execution failed with status: ${result.status}`);
}
return result;
}
}
/**
* Step statement once handling potential IO (for partial sync)
* Matches Python's _step_once_with_io pattern
*
* @returns Status code
*/
private async stepWithIo(): Promise<number> {
while (true) {
const status = this._statement.step();
if (status === TursoStatus.IO) {
// Statement needs IO (e.g., loading missing pages with partial sync)View on GitHub (pinned to bad083fafb)
Solutions
- Map the numeric status to the TursoStatus enum from '@tursodatabase/sync-react-native' to identify the real failure
- Status 129 (CONSTRAINT): fix the data or add an ON CONFLICT clause / upsert to the SQL
- Status 4 (BUSY): serialize writers or retry the operation after a short backoff
- Status 130/131 (READONLY/DATABASE_FULL): check how the database was opened and free device storage
- Status 128 (MISUSE): verify the number of bound parameters matches the statement's placeholders
Example fix
// before
await db.exec(stmt, [duplicateId]); // throws: Statement execution failed with status: 129
// after
const fresh = db.prepare('INSERT INTO t(id) VALUES (?) ON CONFLICT(id) DO UPDATE SET id=excluded.id');
await db.exec(fresh, [duplicateId]); Defensive patterns
Strategy: try-catch
Validate before calling
import { TursoStatus } from '@tursodatabase/sync-react-native';
function describeStatus(e: unknown): string | null {
const m = /status: (\d+)$/.exec(e instanceof Error ? e.message : '');
return m ? TursoStatus[Number(m[1])] ?? `UNKNOWN(${m[1]})` : null;
} Type guard
function isStatusError(e: unknown, status: TursoStatus): boolean {
return e instanceof Error && e.message.endsWith(`status: ${status}`);
} Try / catch
try {
await db.exec(stmt, params);
} catch (e) {
if (isStatusError(e, TursoStatus.BUSY)) {
await new Promise(r => setTimeout(r, 50));
return db.exec(stmt, params); // bounded retry
}
if (isStatusError(e, TursoStatus.CONSTRAINT)) {
// duplicate key etc. — surface a domain error, not a crash
throw new DuplicateKeyError(primaryKey);
}
throw e;
} Prevention
- Keep the TursoStatus enum imported so numeric codes can be decoded at the catch site
- Write UNIQUE-sensitive inserts as upserts (ON CONFLICT DO ...) when duplicates are expected
- Serialize writers through a single queue to avoid BUSY contention
- Validate bound parameter counts/types before exec to avoid MISUSE (128)
When it happens
Trigger: INSERT/UPDATE/DELETE through db.exec() or a Transaction that violates UNIQUE, NOT NULL, or a foreign key (status 129); writing to a read-only database (130); device storage exhausted mid-transaction (131); another connection holding the write lock (4); binding mismatches or reusing a misused statement (128).
Common situations: Duplicate-key inserts inside Transaction.run(); migrating code from better-sqlite3/libsql and expecting string error codes like 'SQLITE_CONSTRAINT' but getting 129; MVCC/multi-connection contention surfacing as 4; large sync writes filling device storage.
Related errors
- Statement step failed with status: ${status}
- getAllRows failed with status: ${bulk.status}
- Statement finalization failed with status: ${status}
- push() is only available for sync databases
- pull() is only available for sync databases
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/9bf65606e9124363.
Report an issue: GitHub.