Skip to content

sqlite: StatementSync#iterate fails with Error: statement has been finalized #57493

Closed
@melusc

Description

@melusc

Version

v23.10.0

Platform

- Microsoft Windows NT 10.0.26100.0 x64
- Microsoft Windows Server 2022 10.0.20348 (Github actions)
- Ubuntu 24.04.2 LTS (Github actions)

Subsystem

sqlite

What steps will reproduce the bug?

index.js

// = Setup =
import { DatabaseSync } from "node:sqlite";

const database = new DatabaseSync(":memory:");

database.exec(`
	CREATE TABLE users (
		user_id  INTEGER PRIMARY KEY AUTOINCREMENT,
		name     TEXT NOT NULL UNIQUE
	);
`);

for (let index = 0; index < 1e3; ++index) {
	database.prepare(`INSERT INTO users (name) VALUES (:name);`).run({
		name: Math.random().toString(36).slice(2),
	});
}

// Double check all 1000 rows are inserted
console.log(database.prepare("SELECT count(*) as row_count FROM users;").get());

// = Actual buggy behaviour starts here =

// const iter = [...database.prepare('SELECT * from users;').iterate()][Symbol.iterator]();
const iter = database.prepare("SELECT * from users;").iterate();

for (const row of iter) {
	console.log(row.user_id, row.name);
}
node index.js

How often does it reproduce? Is there a required condition?

Happens every time. Sometimes it errors, sometimes it just stops unexpectedly without an error.

It doesn't reproduce if you uncomment the line where I fetch all rows immediately by spreading it into an array and then turning it back into an iterator, so the issue comes from reading each value over time.

What is the expected behavior? Why is that the expected behavior?

It should not error and it should print 1000 rows.

What do you see instead?

90% of runs

293 27p5p7fqtms
294 pn2ij0uxxsq
[...]/sqlite-iterate.js:25
for (const row of iter) {
           ^

Error: statement has been finalized
    at [...]/sqlite-iterate.js:25:12
    at ModuleJob.run (node:internal/modules/esm/module_job:274:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:644:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:98:5) {
  code: 'ERR_INVALID_STATE'
}

Node.js v23.10.0

OR

10% it just stops without an error. It should have printed up to 1000.

279 pjvk19yrl7h
280 xrj1kp6l93
281 e73tq3381ff
282 q93lik5apn
283 6kx6awjjuce
284 3h47eaan34j
285 rkrljlp5qnm
PS [...]\5d9342b0-468e-4b12-b854-28a5775d2fab> 

Sometimes the values of the last "successful" row is garbage. Sometimes for name it prints undefined or something like ÙÙ¥Ñ88. The name should always match 0-9a-z so there is some sort of corruption, too.

Additional information

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues with confirmed bugs.sqliteIssues and PRs related to the SQLite subsystem.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions