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:
-- ❌ 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);
### 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
1. **Check array column access**: Verify array indexing in data source queries
2. **Review pipe SQL**: Ensure array access uses one-based indexing
3. **Test with tb sql**: Use CLI to test array access patterns
4. **Validate JSON processing**: Check JSON array access in transformations
5. **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
1. **Always use one-based indexing** for arrays and tuples in ClickHouse
2. **Remember ClickHouse indexing** starts from 1, not 0
3. **Use array functions** like `arrayElement()` for safe access
4. **Check array bounds** before accessing elements
5. **Test array operations** with simple examples first
6. **Document array access patterns** for your team
7. **Use Query Builder** to test array operations interactively
8. **Handle empty arrays** gracefully in your queries
## See also
- [Array Functions](/sql-reference/functions/array-functions) - Array manipulation functions
- [Tuple Functions](/sql-reference/functions/tuple-functions) - Tuple manipulation functions
- [JSON Functions](/sql-reference/functions/json-functions) - JSON processing functions
- [Data Types](/sql-reference/data-types) - Array and tuple data types
- [Error Handling](/forward/dev-reference/common-error-patterns) - General error handling patterns