The "DB::Exception: Illegal column" error in ClickHouse means that a column's data type is not valid for the operation being performed. While similar to ILLEGAL_TYPE_OF_ARGUMENT, this error focuses on the column itself rather than a function parameter — it often arises when you try to use a constant where a column is needed, or when an operation requires a specific column type (like an array or a map) and receives something else.
Impact
The query is rejected at analysis or execution time. This is a relatively common error in complex queries involving lambda functions, higher-order array operations, or type-specific operators. It blocks the query from returning any results.
Common Causes
- Using a literal or constant where a column reference is expected — for instance, passing a constant to a function that only works with column references.
- Applying array operations to non-array columns — using
arrayMap,arrayFilter, or similar on a scalar column. - Map operations on non-Map types — calling
mapKeys()ormapValues()on a column that isn't a Map. - Incorrect lambda expressions — the lambda function's argument types don't match the array element types.
- Using a column in an unsupported context — for example, attempting arithmetic on a String column without casting.
Troubleshooting and Resolution Steps
Check the error details. The message typically includes the function name, the column name, and its type. This tells you exactly what went wrong.
Verify the column type:
SELECT name, type FROM system.columns WHERE database = 'your_db' AND table = 'your_table' AND name = 'the_column';Cast or convert the column to the expected type:
-- Example: convert to Array if working with array functions SELECT arrayJoin(JSONExtract(json_col, 'items', 'Array(String)')) FROM your_table;Use
materialize()for constant-to-column conversion. Some functions require a column, not a constant:-- If the function rejects a constant SELECT someFunction(materialize(42)) FROM your_table;Fix lambda expressions. Ensure the lambda arguments match the array element types:
-- Correct: lambda argument matches array element SELECT arrayMap(x -> x * 2, array_of_ints) FROM your_table;Check for type wrapper differences. LowCardinality, Nullable, and Array wrapping can cause unexpected ILLEGAL_COLUMN errors. Use
toTypeName()to see exactly what ClickHouse is working with.
Best Practices
- Use
toTypeName(column)when debugging to see the full type including wrappers like Nullable, LowCardinality, and Array nesting levels. - When writing higher-order functions (arrayMap, arrayFilter, etc.), verify that the lambda argument types align with the array element type.
- Avoid mixing constants and columns in contexts where ClickHouse expects one or the other — use
materialize()to convert constants to columns when needed. - Keep queries simple and compose complex transformations step by step, checking types at each stage.
Frequently Asked Questions
Q: What is the difference between ILLEGAL_COLUMN and ILLEGAL_TYPE_OF_ARGUMENT?
A: ILLEGAL_TYPE_OF_ARGUMENT is about a function receiving the wrong type. ILLEGAL_COLUMN is broader — it can mean the column itself is not valid in this context, such as using a constant where a column is needed, or a non-array where an array is expected.
Q: Why do I get this error when using arrayMap with a simple expression?
A: Make sure you are passing an actual Array column. If the column is a String that looks like an array, you need to parse it into an Array first. Also verify the lambda syntax is correct: arrayMap(x -> expression, array_column).
Q: Can materialize() fix all ILLEGAL_COLUMN errors?
A: Only those caused by the constant-vs-column distinction. If the underlying type is wrong (e.g., String instead of Array), you need to cast or restructure the data.
Q: Does LowCardinality ever cause this error?
A: Rarely. Most functions handle LowCardinality transparently. However, some specialized operations may reject it. In those cases, cast with CAST(col AS String) or the appropriate base type.