The "DB::Exception: Query parameter value is invalid" error in ClickHouse occurs when a parameterized query receives a parameter value that cannot be parsed or is otherwise invalid. The error code is BAD_QUERY_PARAMETER (code 457). ClickHouse supports parameterized queries where values are passed separately from the query text, and this error indicates that one of those values is malformed.
Impact
The query is rejected before execution. No data is read, written, or modified. This is a client-side issue that requires fixing the parameter value or its type specification. It commonly appears in application code that dynamically constructs parameterized queries.
Common Causes
- Type mismatch between parameter value and declared type -- passing a string value for a parameter declared as
UInt64, or a non-date string for aDateparameter. - Value out of range for the declared type -- supplying a value that parses but exceeds the range of the type, such as a negative number for a
UIntparameter or an oversized integer. - Incorrect parameter syntax -- using wrong placeholder syntax or malformed parameter declarations. (Note: a parameter that is referenced but not supplied at all raises
UNKNOWN_QUERY_PARAMETER, code 456, rather thanBAD_QUERY_PARAMETER.) - Special characters in string parameters -- values containing characters that interfere with parsing when not properly escaped.
- NULL or empty values for non-Nullable parameters -- passing null or empty where a concrete value is expected.
- Array or tuple parameter formatting issues -- complex types require specific formatting that is easy to get wrong.
Troubleshooting and Resolution Steps
Check the parameter syntax in your query:
-- Correct parameterized query syntax SELECT * FROM events WHERE date >= {start_date:Date} AND user_id = {uid:UInt64};Verify parameter values match their declared types:
# Via clickhouse-client clickhouse-client --param_start_date='2024-01-01' --param_uid='12345' \ --query "SELECT * FROM events WHERE date >= {start_date:Date} AND user_id = {uid:UInt64}"Via HTTP, pass parameters as query string arguments:
curl -s "http://localhost:8123/?param_start_date=2024-01-01¶m_uid=12345" \ --data-binary "SELECT * FROM events WHERE date >= {start_date:Date} AND user_id = {uid:UInt64}"For string parameters, ensure proper escaping:
# String values with special characters clickhouse-client --param_name="O'Brien" \ --query "SELECT * FROM users WHERE name = {name:String}"Debug by testing with literal values first:
-- Replace the parameter with a literal to verify the query works SELECT * FROM events WHERE date >= '2024-01-01' AND user_id = 12345; -- Then switch back to parametersFor array parameters, use the correct format:
clickhouse-client --param_ids="[1,2,3]" \ --query "SELECT * FROM events WHERE user_id IN {ids:Array(UInt64)}"Read the error message for the offending parameter. It names the parameter and the type it failed to parse into, which points directly at the value that needs correcting.
Best Practices
- Always declare parameter types explicitly in the query placeholder (
{name:Type}) to get clear error messages when values do not match. - Validate parameter values in your application code before sending them to ClickHouse.
- Use parameterized queries instead of string concatenation to prevent SQL injection and make type handling explicit.
- Test parameterized queries with edge cases: empty strings, zero values, very large numbers, special characters, and NULL values.
- Document the expected parameter types for each query in your codebase.
Frequently Asked Questions
Q: What is the syntax for parameterized queries in ClickHouse?
A: Use {parameter_name:Type} in the query text. Pass values via --param_parameter_name=value in the CLI, or param_parameter_name=value in the HTTP query string. The Type must be a valid ClickHouse type like String, UInt64, Date, etc.
Q: Can I use parameterized queries with INSERT statements?
A: Yes. Parameters can be used in any part of a query where a literal value is expected, including INSERT ... SELECT, WHERE clauses, and LIMIT clauses.
Q: How do I pass a NULL value as a parameter?
A: Declare the parameter as a Nullable type: {param:Nullable(UInt64)}. Then pass the string \N or NULL as the value.
Q: Are parameterized queries cached differently than regular queries?
A: ClickHouse substitutes parameter values into the query before execution, so two requests with different values are treated as distinct queries. With the query result cache enabled, each distinct parameter value produces its own cache entry rather than sharing one. Parameterized queries do, however, keep the query text consistent, which avoids polluting the cache with syntactically different but logically equivalent queries that string concatenation would produce.