ZERO_ARRAY_OR_TUPLE_INDEX ClickHouse error¶
Common cause: You're trying to access a tuple element using zero-based indexing, but ClickHouse uses one-based indexing for tuples.
The ZERO_ARRAY_OR_TUPLE_INDEX
error occurs when you try to access tuple elements using zero-based indexing (starting from 0), but ClickHouse uses one-based indexing (starting from 1) for tuples. Note that arrays use 0-based indexing in ClickHouse.
What causes this error¶
This error typically happens when:
- Zero-based tuple indexing: Using index 0 to access the first tuple element
- Tuple access patterns: Following programming language conventions that use zero-based indexing
- Tuple element access: Trying to access tuple elements with zero-based indices
- JSON array access: Accessing JSON array elements with zero-based indexing (returns empty string)
- String array operations: Using zero-based indices with string arrays (returns empty string)
- Nested array access: Accessing nested array elements incorrectly
Example errors¶
-- Error: Zero-based tuple access SELECT tuple.0 FROM (SELECT (1, 2, 3) AS tuple); -- Error: JSON array with zero index (returns empty string) SELECT JSONExtractString('["a", "b", "c"]', 0); -- Error: String array with zero index (returns empty string) SELECT splitByChar(',', 'a,b,c')[0]; -- Error: Nested array with zero index SELECT array[0][0] FROM (SELECT [[1, 2], [3, 4]] AS array);
Array indexing with [0]
actually works in ClickHouse (0-based indexing). Only tuple indexing with .0
produces the error. JSON and string array indexing with 0
returns empty strings rather than errors.
How to fix it¶
1. Use one-based indexing¶
Always use index 1 for the first element in ClickHouse:
-- ❌ Wrong: Zero-based tuple indexing SELECT tuple.0 FROM (SELECT (1, 2, 3) AS tuple); -- ✅ Correct: One-based tuple indexing SELECT tuple.1 FROM (SELECT (1, 2, 3) AS tuple); -- ✅ Correct: Zero-based array indexing (arrays use 0-based indexing) SELECT array[0] FROM (SELECT [1, 2, 3] AS array);
-- ❌ Wrong: Zero-based tuple access SELECT tuple.0 FROM (SELECT (1, 2, 3) AS tuple);
-- ✅ Correct: One-based tuple access SELECT tuple.1 FROM (SELECT (1, 2, 3) AS tuple);
### 2. Fix JSON array access Use proper JSON array indexing: ```sql -- ❌ Wrong: Zero-based JSON array access SELECT JSONExtractString('["a", "b", "c"]', 0); -- ✅ Correct: One-based JSON array access SELECT JSONExtractString('["a", "b", "c"]', 1); -- ❌ Wrong: Zero-based nested JSON access SELECT JSONExtractString('{"items": ["a", "b", "c"]}', 'items', 0); -- ✅ Correct: One-based nested JSON access SELECT JSONExtractString('{"items": ["a", "b", "c"]}', 'items', 1);
3. Fix string array operations¶
Use proper string array indexing:
-- ❌ Wrong: Zero-based string array access SELECT splitByChar(',', 'a,b,c')[0]; -- ✅ Correct: One-based string array access SELECT splitByChar(',', 'a,b,c')[1]; -- ❌ Wrong: Zero-based array element access SELECT arrayElement(splitByChar(',', 'a,b,c'), 0); -- ✅ Correct: One-based array element access SELECT arrayElement(splitByChar(',', 'a,b,c'), 1);
Use arrayElement(arr, index)
if you need dynamic indexing. Out-of-bounds indexes return NULL rather than error in arrayElement()
.
4. Handle nested arrays¶
Use proper indexing for nested arrays:
-- ❌ Wrong: Zero-based nested array access SELECT array[0][0] FROM (SELECT [[1, 2], [3, 4]] AS array); -- ✅ Correct: One-based nested array access SELECT array[1][1] FROM (SELECT [[1, 2], [3, 4]] AS array); -- ❌ Wrong: Zero-based array element SELECT arrayElement(arrayElement([[1, 2], [3, 4]], 0), 0); -- ✅ Correct: One-based array element SELECT arrayElement(arrayElement([[1, 2], [3, 4]], 1), 1);
Common patterns and solutions¶
Array indexing¶
-- ❌ Wrong: Zero-based array access SELECT my_array[0] FROM my_table; -- ✅ Correct: One-based array access SELECT my_array[1] FROM my_table; -- ❌ Wrong: Zero-based array element function SELECT arrayElement(my_array, 0) FROM my_table; -- ✅ Correct: One-based array element function SELECT arrayElement(my_array, 1) FROM my_table;
Tuple access¶
-- ❌ Wrong: Zero-based tuple access SELECT my_tuple.0 FROM my_table; -- ✅ Correct: One-based tuple access SELECT my_tuple.1 FROM my_table; -- ❌ Wrong: Zero-based tuple element SELECT tupleElement(my_tuple, 0) FROM my_table; -- ✅ Correct: One-based tuple element SELECT tupleElement(my_tuple, 1) FROM my_table;
JSON array access¶
-- ❌ Wrong: Zero-based JSON array SELECT JSONExtractString(json_data, 0) FROM my_table; -- ✅ Correct: One-based JSON array SELECT JSONExtractString(json_data, 1) FROM my_table; -- ❌ Wrong: Zero-based nested JSON SELECT JSONExtractString(json_data, 'items', 0) FROM my_table; -- ✅ Correct: One-based nested JSON SELECT JSONExtractString(json_data, 'items', 1) FROM my_table;
Advanced solutions¶
Using array functions safely¶
-- Safe array access with bounds checking SELECT CASE WHEN length(my_array) >= 1 THEN my_array[1] ELSE NULL END AS first_element FROM my_table; -- Safe tuple access with validation SELECT CASE WHEN tupleLength(my_tuple) >= 1 THEN tupleElement(my_tuple, 1) ELSE NULL END AS first_tuple_element FROM my_table;
Dynamic array access¶
-- Access array elements dynamically SELECT array[1] AS first_element, array[2] AS second_element, array[3] AS third_element FROM ( SELECT [1, 2, 3, 4, 5] AS array );
JSON array processing¶
-- Process JSON arrays safely SELECT JSONExtractString(json_array, 1) AS first_item, JSONExtractString(json_array, 2) AS second_item, JSONExtractString(json_array, 3) AS third_item FROM my_table WHERE JSONHas(json_array, 1);
Tinybird-specific notes¶
In Tinybird, this error commonly occurs when:
- Data source processing: Accessing array columns with zero-based indexing
- Pipe transformations: Using arrays in pipe SQL with wrong indexing
- JSON data processing: Accessing JSON array elements incorrectly
- String processing: Using string arrays with zero-based indexing
Debugging in Tinybird¶
- Check array column access: Verify array indexing in data source queries
- Review pipe SQL: Ensure array access uses one-based indexing
- Test with tb sql: Use CLI to test array access patterns
- Validate JSON processing: Check JSON array access in transformations
- Use Query Builder: Test array operations interactively
Common Tinybird scenarios¶
-- In data source definitions, handle array columns properly SCHEMA > `timestamp` DateTime, `user_id` UInt32, `tags` Array(String), `scores` Array(Float64) -- ❌ Wrong: Zero-based array access in pipe NODE processed_data SQL > SELECT timestamp, user_id, tags[0] AS primary_tag FROM your_data_source; -- ✅ Correct: One-based array access in pipe NODE processed_data SQL > SELECT timestamp, user_id, tags[1] AS primary_tag FROM your_data_source;
Array data processing¶
-- In pipe definitions, handle arrays safely NODE array_processing SQL > SELECT user_id, arrayElement(tags, 1) AS first_tag, arrayElement(scores, 1) AS first_score FROM your_data_source WHERE length(tags) > 0;
Best practices¶
- Always use one-based indexing for arrays and tuples in ClickHouse
- Remember ClickHouse indexing starts from 1, not 0
- Use array functions like
arrayElement()
for safe access - Check array bounds before accessing elements
- Test array operations with simple examples first
- Document array access patterns for your team
- Use Query Builder to test array operations interactively
- Handle empty arrays gracefully in your queries
See also¶
- Array Functions - Array manipulation functions
- Tuple Functions - Tuple manipulation functions
- JSON Functions - JSON processing functions
- Data Types - Array and tuple data types
- Error Handling - General error handling patterns