Description
OpenClaw uses statement.columns() from Node's built-in node:sqlite module (in openclaw-state-db-*.js) to distinguish SELECT queries from INSERT/UPDATE/DELETE:
// Line ~85
if (stmt.columns().length > 0) return Promise.resolve({ rows: stmt.all(...sqliteParameters) });
// Line ~139
if (statement.columns().length > 0) return { rows: statement.all(...parameters) };
On Node 22, StmtSync.prototype.columns is a function that returns column metadata.
On Node 23.7.0+ (and confirmed on 26), statement.columns is undefined — the method was removed at some point during the experimental node:sqlite lifecycle.
Impact
[openclaw] Could not start the CLI.
[openclaw] Reason: Failed to open the plugin state database. | statement.columns is not a function
This affects openclaw status, openclaw doctor, and any CLI command that touches the plugin state database. The gateway itself may still run if it was already loaded, but any restart will hit this.
Environment
- OpenClaw: 2026.6.1 → 2026.6.2-beta.1 (both affected)
- Node: 23.7.0
- OS: macOS 26.3.1 (arm64)
Temporary Workaround
Replace stmt.columns().length > 0 with a check using sourceSQL:
stmt.sourceSQL.trim().toUpperCase().startsWith("SELECT")
This works because sourceSQL is available on both Node 22 and 23.
Suggested Fix
Use statement.sourceSQL (already available in the StmtSync prototype) instead of the removed columns(). Or add a feature detection shim:
function isSelectStatement(stmt) {
if (typeof stmt.columns === "function") {
return stmt.columns().length > 0;
}
return stmt.sourceSQL?.trim().toUpperCase().startsWith("SELECT") ?? false;
}
This would maintain backward compatibility with Node 22 while fixing Node 23+.
Description
OpenClaw uses
statement.columns()from Node's built-innode:sqlitemodule (inopenclaw-state-db-*.js) to distinguish SELECT queries from INSERT/UPDATE/DELETE:On Node 22,
StmtSync.prototype.columnsis a function that returns column metadata.On Node 23.7.0+ (and confirmed on 26),
statement.columnsisundefined— the method was removed at some point during the experimentalnode:sqlitelifecycle.Impact
This affects
openclaw status,openclaw doctor, and any CLI command that touches the plugin state database. The gateway itself may still run if it was already loaded, but any restart will hit this.Environment
Temporary Workaround
Replace
stmt.columns().length > 0with a check usingsourceSQL:This works because
sourceSQLis available on both Node 22 and 23.Suggested Fix
Use
statement.sourceSQL(already available in the StmtSync prototype) instead of the removedcolumns(). Or add a feature detection shim:This would maintain backward compatibility with Node 22 while fixing Node 23+.