tursodatabase/turso · error · DatabaseError
SQL execution failed
Error message
SQL execution failed
What it means
DatabaseError thrown while consuming the cursor stream of Session.execute() — the path behind Connection/Transaction run/get/all and Statement execution — when the server sends a step_error or fatal error entry. The server's message is preferred; the literal 'SQL execution failed' is the fallback for entries that carry no error.message.
Source
Thrown at serverless/javascript/src/session.ts:385
if (entry.row) {
const decodedRow = entry.row.map(value => decodeValue(value, safeIntegers));
const rowObject = this.createRowObject(decodedRow, columns);
rows.push(rowObject);
}
break;
case 'step_end':
if (entry.affected_row_count !== undefined) {
rowsAffected = entry.affected_row_count;
}
if (entry.last_insert_rowid !== undefined && entry.last_insert_rowid !== null) {
lastInsertRowid = typeof entry.last_insert_rowid === 'number'
? entry.last_insert_rowid
: parseInt(entry.last_insert_rowid, 10);
}
break;
case 'step_error':
case 'error':
throw new DatabaseError(entry.error?.message || 'SQL execution failed', entry.error?.code);
}
}
return {
columns,
columnTypes,
rows,
rowsAffected,
lastInsertRowid
};
}
/**
* Create a row object with both array and named property access.
*
* @param values - Array of column values
* @param columns - Array of column names
* @returns Row object with dual access patternsView on GitHub (pinned to bad083fafb)
Solutions
- Read the server message and DatabaseError.code (e.g. SQLITE_CONSTRAINT_UNIQUE) — they identify the failing statement and reason
- Fix the data or schema the message points to (ON CONFLICT clauses, migrations, validated input)
- If only the fallback text appears, capture the raw response via a logging proxy and report the server issue
Example fix
// before
await db.run("INSERT INTO users(id) VALUES (?)", 1); // duplicate id -> step_error
// after
await db.run("INSERT INTO users(id) VALUES (?) ON CONFLICT(id) DO NOTHING", 1); Defensive patterns
Strategy: try-catch
Type guard
const isDatabaseError = (e: unknown): e is Error & { code?: string } =>
e instanceof Error && e.name === "DatabaseError"; Try / catch
try {
await db.run(sql, ...args);
} catch (e) {
const code = (e as { code?: string })?.code;
if (code === "SQLITE_CONSTRAINT_UNIQUE") {
// duplicate key: upsert or skip
} else if (code === "SQLITE_BUSY") {
// write contention: back off and retry
} else throw e;
} Prevention
- Branch on DatabaseError.code rather than parsing messages — codes are stable
- Validate input data (uniqueness, NOT NULL, FK targets) before binding
- Wrap groups of dependent writes in transactionAsync so a failure rolls the group back
When it happens
Trigger: Runtime SQL failures surfacing from db.run()/db.get()/db.all() or tx equivalents: UNIQUE/NOT NULL constraint violations, 'no such table/column', SQLITE_BUSY write contention; malformed message-less error entries from a buggy server triggering the fallback text.
Common situations: INSERTs violating constraints with unvalidated data; referencing tables that don't exist in the deployed database; concurrent writers hitting lock timeouts; server bugs emitting errors without messages.
Related errors
- Describe execution failed
- The supplied SQL string contains no statements
- Unexpected describe response
- Batch execution failed
- Sequence execution failed
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/ee2367089bd4d23d.
Report an issue: GitHub.