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

  1. Log/inspect the offending params array and find the value whose typeof is unsupported (the message names the type).
  2. Coerce undefined/null values explicitly before escaping (e.g. use null and ensure the switch handles it, or stringify the value).
  3. Convert unsupported types to supported primitives: String(v) for symbols, Number(v) for bigint if safe, call the function to get its value.
  4. 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

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


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/2b8b831dadc3fe1a. Report an issue: GitHub.