earendil-works/pi · error · TypeError
SQLite transaction callbacks must be synchronous
Error message
SQLite transaction callbacks must be synchronous
What it means
Guard inside the synchronous SQLite transaction wrapper: the callback passed to transaction() returned a thenable (isAsyncResult detected a Promise/async result). The wrapper has already executed BEGIN IMMEDIATE and cannot hold the write transaction across an await, so it aborts the COMMIT path and rolls back rather than corrupting transactional state.
Solutions
- Make the transaction callback synchronous; async callbacks are not supported inside SQLite transactions.
Defensive patterns
Strategy: type-guard
When it happens
Trigger: Thrown at packages/session-backends/sqlite-node/src/index.ts:82 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24).
Data as JSON: /api/errors/a800361a8ab20076.
Report an issue: GitHub.
Appendix: source
Thrown at packages/session-backends/sqlite-node/src/index.ts:82
constructor(db: DatabaseSync) {
this.db = db;
}
exec(sql: string): void {
this.db.exec(sql);
}
prepare(sql: string): SqliteStatement {
return new NodeSqliteStatement(this.db.prepare(sql));
}
transaction<T>(fn: () => T): T {
sql`BEGIN IMMEDIATE`.exec(this);
try {
const result = fn();
if (isAsyncResult(result)) {
throw new TypeError("SQLite transaction callbacks must be synchronous");
}
sql`COMMIT`.exec(this);
return result;
} catch (error) {
try {
sql`ROLLBACK`.exec(this);
} catch {
// Ignore rollback errors to rethrow original error.
}
throw error;
}
}
close(): void {
this.db.close();
}
}
View on GitHub (pinned to 4af9d21d3b)