tursodatabase/turso · error · Error
Unsupported parameter type
Error message
Unsupported parameter type: ${typeof value} What it means
bindValue() accepts numbers (int via bindPositionalInt, floats via bindPositionalDouble), strings (bindPositionalText), and blob data (ArrayBuffer or typed-array views via bindPositionalBlob). Anything else — null/undefined, booleans, plain objects, arrays, Dates — falls through to this TypeError describing the offending typeof.
Solutions
- Map values before binding: null/undefined -> sql null support via explicit conversion your schema expects (e.g. bind 0/'' or restructure to avoid the slot), booleans -> 0/1, Dates -> ISO strings, objects/arrays -> JSON.stringify
- Add a normalize(value) helper at your data layer so every bound value is number|string|ArrayBuffer
- Type your params as SQLiteValue (number | string | ArrayBuffer | TypedArray) so invalid types fail at compile time
Example fix
// before
await stmt.run({
id: 1,
active: true, // typeof 'boolean'
created: new Date(), // typeof 'object'
});
// after
await stmt.run({
id: 1,
active: 1,
created: new Date().toISOString(),
}); Defensive patterns
Strategy: validation
Validate before calling
type SqlValue = number | string | ArrayBuffer;
function normalize(v: unknown): SqlValue {
if (v == null) return ''; // or model NULL explicitly per your schema
if (typeof v === 'boolean') return v ? 1 : 0;
if (v instanceof Date) return v.toISOString();
if (typeof v === 'object') return JSON.stringify(v);
if (typeof v === 'number' || typeof v === 'string') return v;
throw new Error(`Cannot bind value of type ${typeof v}`);
}
const safeParams = rawParams.map(normalize);
await stmt.run(...safeParams); Type guard
function isBindable(v: unknown): v is number | string | ArrayBuffer | ArrayBufferView {
return (
typeof v === 'number' ||
typeof v === 'string' ||
v instanceof ArrayBuffer ||
ArrayBuffer.isView(v)
);
} Try / catch
try {
await stmt.run(params);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unsupported parameter type:')) {
throw new TypeError(`Bound value not a SQLite type: got ${e.message.split(': ')[1]}. Convert booleans/Dates/objects first.`);
}
throw e;
} Prevention
- Normalize at the data-layer boundary: booleans -> 0/1, Dates -> ISO strings, objects -> JSON.stringify, null -> explicit SQL NULL strategy
- Type bind params as number | string | ArrayBuffer (or typed-array views) so invalid kinds fail at compile time
- Never assume JSON columns auto-serialize — this binding only accepts SQLite scalars and blobs
When it happens
Trigger: Binding null or undefined (e.g. optional field that is unset), a boolean flag, a Date object, a plain object/array expecting JSON serialization, or a BigInt — all reach the final else branch of bindValue.
Common situations: Inserting API payloads where fields can be null; passing `true/false` for a column stored as 0/1; forgetting to call date.toISOString(); assuming JSON columns auto-serialize; BigInt keys from other libraries.
Related errors
- Unknown parameter name
- getAllRows failed with status
- Statement execution failed with status
- Statement has been finalized
- Statement step failed with status
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/e1bc9d57de3d3042.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/react-native/src/Statement.ts:118
* @param value - Value to bind
*/
private bindValue(position: number, value: SQLiteValue): void {
if (value === null || value === undefined) {
this._statement.bindPositionalNull(position);
} else if (typeof value === 'number') {
// Check if integer or float
if (Number.isInteger(value)) {
this._statement.bindPositionalInt(position, value);
} else {
this._statement.bindPositionalDouble(position, value);
}
} else if (typeof value === 'string') {
this._statement.bindPositionalText(position, value);
} else if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
const buffer = value as unknown as ArrayBuffer;
this._statement.bindPositionalBlob(position, buffer);
} else {
throw new Error(`Unsupported parameter type: ${typeof value}`);
}
}
/**
* Execute statement without returning rows (for INSERT, UPDATE, DELETE)
*
* @param params - Optional parameters to bind
* @returns Result with changes and lastInsertRowid
*/
async run(...params: BindParams[]): Promise<RunResult> {
if (this._finalized) {
throw new Error('Statement has been finalized');
}
if (this._execLock) {
await this._execLock.acquire();
}
try {View on GitHub (pinned to 244cde92a7)