can1357/oh-my-pi · error · ToolError
SQLite column '${column}' only accepts JSON scalar values or
Error message
SQLite column '${column}' only accepts JSON scalar values or null What it means
Thrown by normalizeWriteValue when a value supplied for a column write is not a JSON scalar (string, number, boolean, bigint) or null. Object/array values cannot be bound as SQLite parameters, so the tool rejects them up front rather than producing an opaque binding error.
Source
Thrown at packages/coding-agent/src/tools/sqlite-reader.ts:511
if (!trimmed) return undefined;
const violation = findWhereClauseViolation(trimmed);
if (violation) {
throw new ToolError(violation);
}
return trimmed;
}
function normalizeWriteValue(value: unknown, column: string): SqliteBinding {
if (value === null) return null;
if (
typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean" ||
typeof value === "bigint"
) {
return value;
}
throw new ToolError(`SQLite column '${column}' only accepts JSON scalar values or null`);
}
function validateWriteColumns(
db: Database,
table: string,
data: Record<string, unknown>,
): Array<[string, SqliteBinding]> {
const columns = new Set(getTableColumns(db, table));
return Object.entries(data).map(([column, value]) => {
if (!columns.has(column)) {
throw new ToolError(`SQLite table '${table}' has no column named '${column}'`);
}
return [column, normalizeWriteValue(value, column)];
});
}
export function parseSqlitePathCandidates(filePath: string): SqlitePathCandidate[] {
const normalized = filePath.replace(/\\/g, "/");View on GitHub (pinned to 9690622007)
Solutions
- JSON.stringify objects/arrays into strings before writing
- Extract scalars from the object and write individual columns
- Store arrays/objects as JSON text in a TEXT column
- Use null for absent values instead of objects
Example fix
// before
write('config', { meta: { a: 1 } })
// after
write('config', { meta: JSON.stringify({ a: 1 }) }) Defensive patterns
Strategy: type-guard
Validate before calling
function isBindable(v: unknown): boolean {
return v === null || ['string','number','boolean','bigint'].includes(typeof v);
}
for (const [k, v] of Object.entries(data)) {
if (!isBindable(v)) throw new Error(`column '${k}' needs a scalar or null; stringify objects first`);
} Type guard
function isSqliteBinding(v: unknown): v is string | number | boolean | bigint | null {
return v === null || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || typeof v === 'bigint';
} Try / catch
try {
await writer.write('config', data);
} catch (err) {
if (err instanceof ToolError && err.message.includes('only accepts JSON scalar values')) {
// stringify nested values and retry once
} else throw err;
} Prevention
- Flatten or JSON.stringify nested objects/arrays before writing
- Type your write payloads as Record<string, string|number|boolean|null>
- Convert Date values to ISO strings before writing
When it happens
Trigger: Writing data where a field is an object or array, e.g. data={meta:{a:1}} or data={tags:[1,2]}; passing undefined nested values; JSON payloads that keep nested structures instead of flattening or stringifying them.
Common situations: Inserting parsed JSON documents directly into a table; forgetting to JSON.stringify nested config blobs; ORM-style code that passes Date objects or arrays.
Related errors
- SQLite table '${table}' has no column named '${column}'
- Unsupported SQLite selector
- SQLite limit must be a positive integer; got '${value}'
- SQLite offset must be a non-negative integer; got '${value}'
- ${label} must be an integer; got '${key}'
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/0d47e5e502114c68.
Report an issue: GitHub.