This error occurs when the XREAD or XREADGROUP command lacks matching stream IDs for each stream key. Redis requires equal numbers of stream keys and stream IDs in the STREAMS clause.
The "ERR Unbalanced XREAD list of streams" error is thrown by Redis when you attempt to read from streams using XREAD or XREADGROUP commands without providing the correct number of stream entry IDs. The XREAD command syntax requires two parallel lists after the STREAMS keyword: first, all the stream keys you want to read from, followed by all the corresponding stream IDs (or special markers like $ or >) to indicate where to start reading from each stream. When these lists are unbalanced—meaning you have a different number of keys than IDs—Redis cannot determine which ID corresponds to which stream and raises this error. This is a client-side command construction error, not a server or data issue. It commonly appears when using Redis client libraries that abstract the command construction, where developers forget to specify IDs or misconfigure the command arguments.
Check that you're providing equal numbers of stream keys and stream IDs. The correct syntax is:
XREAD STREAMS stream_key1 stream_key2 stream_id1 stream_id2For a single stream reading new messages:
XREAD STREAMS mystream $For multiple streams:
XREAD STREAMS stream1 stream2 stream3 0-0 0-0 0-0Ensure you have exactly one ID for each stream key listed.
If using a Redis client library, verify you're passing the IDs parameter correctly. Different libraries have different APIs:
Node.js (node-redis):
await client.xRead(
{ key: 'mystream', id: '0-0' },
{ BLOCK: 5000 }
);Go (go-redis):
streams, err := client.XRead(ctx, &redis.XReadArgs{
Streams: []string{"mystream", "0-0"}, // Key first, then ID
Count: 10,
Block: 0,
}).Result()Python (redis-py):
client.xread({'mystream': '0-0'}, count=10)Consult your specific client library documentation for the correct parameter structure.
Redis supports special ID values for different reading behaviors:
- $ - Read only new entries (ones added after this command)
- > - For XREADGROUP only, get messages never delivered to any consumer
- 0-0 - Read from the beginning of the stream
- Specific ID - Start reading after a particular entry (e.g., "1609459200000-0")
Example using $ to read new messages:
XREAD BLOCK 0 STREAMS notifications $For XREADGROUP:
XREADGROUP GROUP mygroup consumer1 STREAMS mystream >When reading from multiple streams, ensure you provide IDs in the same order as the keys:
# Correct - 3 streams, 3 IDs
XREAD STREAMS orders payments notifications $ $ $
# Correct - mix of IDs
XREAD STREAMS stream1 stream2 1609459200000-0 $
# Wrong - 3 streams, only 2 IDs (causes error)
XREAD STREAMS orders payments notifications $ $Each stream must have a corresponding ID, even if you use the same special marker for all of them.
Some older versions of Redis client libraries had bugs in XREAD/XREADGROUP implementations. Check if you're using an outdated version:
# Node.js
npm outdated redis
# Python
pip list --outdated | grep redis
# Go
go list -m -u github.com/redis/go-redis/v9Update to the latest stable version:
# Node.js
npm install redis@latest
# Python
pip install --upgrade redis
# Go
go get -u github.com/redis/go-redis/v9Review the changelog for XREAD-related fixes.
Understanding Stream IDs: Redis Stream IDs are composed of two parts: a timestamp in milliseconds and a sequence number (format: "timestamp-sequence"). The special markers $ and > are context-dependent: $ means "start after the last entry currently in the stream" for XREAD, while > means "messages never delivered to any consumer" for XREADGROUP.
Blocking vs Non-Blocking: When using BLOCK with XREAD, the command will wait up to the specified milliseconds for new data to arrive. A BLOCK value of 0 means block indefinitely. The unbalanced streams error occurs during command parsing before any blocking happens, so timeout settings don't affect this error.
Client Library Abstractions: Some client libraries (especially go-redis and node-redis) had historical issues where their higher-level APIs didn't clearly expose the ID parameter requirement. Always check the library's GitHub issues for known XREAD problems, and prefer using stable, well-maintained releases over bleeding-edge versions for production stream consumption.
COUNT Parameter: The COUNT option limits how many entries to return per stream, but doesn't affect the balanced streams requirement. You still need one ID per stream regardless of COUNT value.
ERR syntax error
How to fix "ERR syntax error" in Redis
ConnectionError: Error while reading from socket
ConnectionError: Error while reading from socket in redis-py
ERR unknown command
How to fix ERR unknown command in Redis
Command timed out
How to fix 'Command timed out' in ioredis
ERR DISCARD without MULTI
How to fix "ERR DISCARD without MULTI" in Redis