Summary
When using @surrealdb/node@3.0.3 with surrealdb@2.0.3, calling close() on a surrealkv:// connection does not release the file-level LOCK. A subsequent connect() to the same file hangs indefinitely.
Reproduction
import { Surreal } from "surrealdb";
import { createNodeEngines } from "@surrealdb/node";
const url = "surrealkv:///tmp/test-lock-bug.db";
// First connection — works fine
const db1 = new Surreal({ engines: createNodeEngines() });
await db1.connect(url);
await db1.use({ namespace: "test", database: "test" });
console.log("First connected.");
await db1.close();
console.log("First closed.");
// Second connection — hangs forever
const db2 = new Surreal({ engines: createNodeEngines() });
await db2.connect(url); // ← never resolves
console.log("Second connected."); // ← never reached
Run with: bun -e '<above>' (or npx tsx)
Expected behavior
After close(), the LOCK file should be released and a new connect() to the same surrealkv:// path should succeed.
Actual behavior
The second connect() hangs indefinitely. A LOCK file remains in the database directory after close():
$ ls /tmp/test-lock-bug.db/
LOCK manifest/ sstables/ vlog/ wal/
Reproduced consistently (3/3 attempts, fresh database paths each time).
Environment
@surrealdb/node: 3.0.3
surrealdb (JS SDK): 2.0.3
- Runtime: Bun 1.3.11 (macOS arm64, Darwin 25.3.0)
- Also reproducible pattern: any code that opens sequential connections to the same
surrealkv:// file (e.g., connection pooling, service restart, database migration scripts)
Workaround
Use a single shared connection for the lifetime of the process instead of opening/closing connections. The embedded surrealkv engine reflects data changes immediately through an existing connection, so reconnection is unnecessary for data freshness. However, this prevents use cases like connection health recovery or graceful restart.
Notes
mem:// connections do not exhibit this behavior — only surrealkv:// file-backed databases
- The issue does not occur with
@surrealdb/node@2.3.5 — it appears to be a regression in v3
Summary
When using
@surrealdb/node@3.0.3withsurrealdb@2.0.3, callingclose()on asurrealkv://connection does not release the file-level LOCK. A subsequentconnect()to the same file hangs indefinitely.Reproduction
Run with:
bun -e '<above>'(ornpx tsx)Expected behavior
After
close(), the LOCK file should be released and a newconnect()to the samesurrealkv://path should succeed.Actual behavior
The second
connect()hangs indefinitely. ALOCKfile remains in the database directory afterclose():Reproduced consistently (3/3 attempts, fresh database paths each time).
Environment
@surrealdb/node: 3.0.3surrealdb(JS SDK): 2.0.3surrealkv://file (e.g., connection pooling, service restart, database migration scripts)Workaround
Use a single shared connection for the lifetime of the process instead of opening/closing connections. The embedded
surrealkvengine reflects data changes immediately through an existing connection, so reconnection is unnecessary for data freshness. However, this prevents use cases like connection health recovery or graceful restart.Notes
mem://connections do not exhibit this behavior — onlysurrealkv://file-backed databases@surrealdb/node@2.3.5— it appears to be a regression in v3