cube-js/cube · error · Error
Unsupported parameter type for SQL escaping: ${typeof value}
Error message
Unsupported parameter type for SQL escaping: ${typeof value} What it means
escapeValueInternal in packages/cubejs-backend-shared/src/sql-escape.ts throws when asked to SQL-escape a value whose runtime type is not one of the supported kinds (string, number, boolean, arrays, plain objects/records). The switch over `typeof value` reaches its `default` arm, meaning the library cannot safely serialize the value into a SQL literal. This is a fail-fast guard against injecting malformed or unsafe SQL parameters.
Source
Thrown at packages/cubejs-backend-shared/src/sql-escape.ts:131
if (typeof obj.toSqlString === 'function') {
return String(obj.toSqlString());
}
if (stringifyObjects) {
return this.escapeString(String(value));
}
return Object.keys(value)
.filter((key) => typeof (value as Record<string, unknown>)[key] !== 'function')
.map((key) => (
`${this.escapeIdentifier(key)} = ${
this.escapeValueInternal((value as Record<string, unknown>)[key], true)
}`
))
.join(', ');
}
default:
throw new Error(`Unsupported parameter type for SQL escaping: ${typeof value}`);
}
}
/**
* Substitutes positional placeholders in `sql` with escaped `values`:
* - `?` is replaced by an escaped value ({@link escapeValue})
* - `??` is replaced by an escaped identifier ({@link escapeIdentifier})
* Longer runs of `?` are left untouched. This mirrors `sqlstring.format`'s
* placeholder semantics so it can be a drop-in replacement in drivers.
*/
public format(sql: string, values?: unknown): string {
if (values === null || values === undefined) {
return sql;
}
const valueList = Array.isArray(values) ? values : [values];
if (valueList.length === 0) {
return sql;View on GitHub (pinned to 7d981676b3)
Solutions
- Log/inspect the offending params array and find the value whose typeof is unsupported (the message names the type).
- Coerce undefined/null values explicitly before escaping (e.g. use null and ensure the switch handles it, or stringify the value).
- Convert unsupported types to supported primitives: String(v) for symbols, Number(v) for bigint if safe, call the function to get its value.
- For structured values, pass a plain object or array so the record-branch of escapeValueInternal escapes it key by key.
Example fix
// before const params = [userId, callbackFn]; const sql = substitute(sqlTemplate, params); // throws: Unsupported parameter type... function // after const params = [userId, callbackFn()]; // pass the value, not the function const sql = substitute(sqlTemplate, params);
Defensive patterns
Strategy: type-guard
Validate before calling
const SUPPORTED = ['string', 'number', 'boolean', 'object'];
params.forEach((v, i) => {
if (v == null) throw new Error(`params[${i}] is ${v}; pass an explicit value`);
if (!SUPPORTED.includes(typeof v)) throw new Error(`params[${i}] has unsupported type ${typeof v}`);
}); Type guard
function isSqlEscapable(v: unknown): v is string | number | boolean | Record<string, unknown> | unknown[] {
return v != null && ['string', 'number', 'boolean', 'object'].includes(typeof v);
} Try / catch
try {
const sql = substitute(template, params);
} catch (e) {
if (/Unsupported parameter type for SQL escaping/.test(String(e))) {
throw new Error(`Bad SQL params at indexes: ${params.map((p,i)=>[p,i]).filter(([p])=>!isSqlEscapable(p)).map(([,i])=>i)}`);
}
throw e;
} Prevention
- Never build params from possibly-unset variables without defaults (value ?? fallback)
- Call functions before placing their results in params arrays
- Convert exotic types (bigint, symbol, Date wrappers) to string/number explicitly
- Keep param construction close to the query so types are visible in review
When it happens
Trigger: Calling escapeValue() (directly or via positional `?` placeholder substitution) with a value of type undefined, function, symbol, bigint, or another exotic type — e.g. escapeValue(undefined) or a params array containing an unset variable or a callback.
Common situations: Building query strings dynamically where a variable was never assigned (undefined), passing a Date-like wrapper class instance, passing a function returned from a factory instead of its result, or refactors that change a param type from number to bigint.
Related errors
- Unexpected input parameter value '${payload.input}'
- Unexpected output parameter value '${payload.output}'
- query parameter must be a non-empty string
- You cannot change security context via __user from ${session
- Incorrect user name "${user}" or password
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/2b8b831dadc3fe1a.
Report an issue: GitHub.