drizzle-team/drizzle-orm · error · Error
Unexpected param value: ${chunk}
Error message
Unexpected param value: ${chunk} What it means
Thrown by SQL.mapInlineParam (sql.ts:322) when a value interpolated into a sql`` template cannot be inlined as a literal. The method handles null, number, boolean, string, and object; anything else (undefined, symbol, bigint, function) reaches the final throw. Inlining only happens for queries built with paramStyle 'inline' (e.g. sqlToQuery for dialects/databases that inline rather than bind placeholders).
Source
Thrown at drizzle-orm/src/sql/sql.ts:322
{ escapeString }: BuildQueryConfig,
): string {
if (chunk === null) {
return 'null';
}
if (typeof chunk === 'number' || typeof chunk === 'boolean') {
return chunk.toString();
}
if (typeof chunk === 'string') {
return escapeString(chunk);
}
if (typeof chunk === 'object') {
const mappedValueAsString = chunk.toString();
if (mappedValueAsString === '[object Object]') {
return escapeString(JSON.stringify(chunk));
}
return escapeString(mappedValueAsString);
}
throw new Error('Unexpected param value: ' + chunk);
}
getSQL(): SQL {
return this;
}
as(alias: string): SQL.Aliased<T>;
/**
* @deprecated
* Use ``sql<DataType>`query`.as(alias)`` instead.
*/
as<TData>(): SQL<TData>;
/**
* @deprecated
* Use ``sql<DataType>`query`.as(alias)`` instead.
*/
as<TData>(alias: string): SQL.Aliased<TData>;
as(alias?: string): SQL<T> | SQL.Aliased<T> {View on GitHub (pinned to b7862528fd)
Solutions
- Ensure the value is one of null/number/boolean/string/object before interpolating; coerce or guard against undefined.
- Use sql.placeholder() or bind parameters through .all()/.run() instead of inlining literals.
- If you genuinely need inline SQL, stringify/serialize unsupported types (BigInt -> String) before interpolation.
Example fix
// before
const q = sql`select * from t where id = ${maybeUndefined}`;
// maybeUndefined === undefined -> 'Unexpected param value: undefined'
// after
const id = maybeUndefined ?? null;
const q = sql`select * from t where id = ${id}`; Defensive patterns
Strategy: validation
Validate before calling
function inlineSafe(value) {
if (value === undefined) return null;
if (typeof value === 'bigint') return value.toString();
if (typeof value === 'symbol' || typeof value === 'function') {
throw new TypeError('Cannot inline ' + typeof value);
}
return value;
}
// then: sql`... ${inlineSafe(maybeUndef)}` Type guard
const isInlineable = (v): boolean => v === null || ['number', 'boolean', 'string', 'object'].includes(typeof v);
Prevention
- Prefer bound parameters (.run(params)) over inline interpolation.
- Coerce undefined to null and bigint to string before interpolating into sql``.
- Avoid interpolating functions/symbols; pass their string representation explicitly if needed.
When it happens
Trigger: Interpolating undefined, a Symbol, a BigInt, or a function/class instance directly into sql`` and then building the query in inline-param mode (typical for SQLite/Prisma-style raw SQL or when using .toSQL() with invoke: 'inline'). Passing a custom column/SQL object whose toString() is not enough is fine, but a bare undefined is the classic trigger.
Common situations: A conditional that left a variable as undefined; a JSON field whose value was stripped to undefined; upgrading drizzle where the default param-inlining behaviour changed; passing a Date to an inline-built query on a path that does not special-case it.
Related errors
- Unknown type for ${value}
- No value for placeholder "${p.name}" was provided
- No value for placeholder "${p.value.name}" was provided
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/1af64189ad1bbc9c.json.
Report an issue: GitHub.