Skip to content

fix: batch Kafka messages are a list under FastStream's test broker - #30

Merged
aradng merged 2 commits into
mainfrom
fix/kafka-batch-message-list-shape
Jul 21, 2026
Merged

fix: batch Kafka messages are a list under FastStream's test broker#30
aradng merged 2 commits into
mainfrom
fix/kafka-batch-message-list-shape

Conversation

@aradng

@aradng aradng commented Jul 21, 2026

Copy link
Copy Markdown
Owner

What

`KafkaSubscriber`'s retry middleware (`_locate()`) only checked isinstance(raw, tuple) to detect a batch message, matching real confluent-kafka's getmany() -> tuple[Message, ...]. FastStream's own confluent test/mock broker wraps batch messages in a plain list instead, so any batch=True subscriber crashes with AttributeError: 'list' object has no attribute 'topic' the instant its retry middleware runs under test.

Found while bumping a downstream service to 0.5.0 — its batch=True Kafka consumer tests failed immediately. This whole retry-middleware code path is new in 0.5.0, so this bug never shipped before now.

Fix

Widened the isinstance check to (list, tuple).

Tests

Added a parametrized regression test that builds both shapes directly. Confirmed methodology: reverted the fix temporarily with the test in place — it fails on list, passes on tuple (matching the bug exactly); reapplied the fix — both pass.

106/106 tests pass, pre-commit run --all-files clean.

aradng and others added 2 commits July 21, 2026 17:41
…er, not just tuple

_locate()'s batch-detection only checked isinstance(raw, tuple),
matching real confluent-kafka's getmany() -> tuple[Message, ...] - but
FastStream's own confluent test/mock broker wraps batch messages in a
plain list instead, so any batch=True subscriber (og_futures, the
arrow-sink CDC consumer) crashed with AttributeError: 'list' object
has no attribute 'topic' the moment its retry middleware ran under
test. Found while bumping a downstream service to 0.5.0 - its batch
consumer test suite failed immediately. This whole code path is new
in 0.5.0, so the bug never shipped before now.

Widened the check to isinstance(raw, (list, tuple)). Added a
parametrized regression test reproducing both shapes directly (before
touching the fix, confirmed it fails on the old code with `list` and
passes with `tuple`).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9p8y4kfiytRMVrzGW4rFN
Same two real shapes (list, tuple) still match, but Sequence also
covers any other indexable container FastStream might switch to later
without needing another patch. Verified a single confluent_kafka.Message
isn't a Sequence, so the non-batch branch is unaffected. Sequence
guarantees __getitem__ (unlike bare Iterable), so raw[0] stays safe -
Iterable would've been too wide and introduced a real crash risk for
non-indexable iterables (sets, generators).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9p8y4kfiytRMVrzGW4rFN
@aradng
aradng merged commit eead5a8 into main Jul 21, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant