Skip to content

Fix stream error handlers raising a tuple instead of an exception - #447

Open
dylanpulver wants to merge 1 commit into
halcy:masterfrom
dylanpulver:fix-streaming-error-tuple
Open

Fix stream error handlers raising a tuple instead of an exception#447
dylanpulver wants to merge 1 commit into
halcy:masterfrom
dylanpulver:fix-streaming-error-tuple

Conversation

@dylanpulver

Copy link
Copy Markdown

streaming.py lines 160 and 165 terminate the MastodonReadTimeout(...) / MastodonNetworkError(...) constructor call with a trailing comma, so exception is a 1-tuple. raise exception from err then raises TypeError: exceptions must derive from BaseException, and on_abort receives the tuple rather than the exception object its docstring promises (streaming.py:86-95).

Knock-on effect: __stream catches (AttributeError, MastodonMalformedEventError, MastodonNetworkError) at internals.py:555 to drive reconnect_async. TypeError is not in that tuple, so a read timeout or a connection reset kills the streaming thread instead of reconnecting.

This is #368. It was closed on the theory that six was responsible; removing six in 945e8e6 turned six.raise_from(tuple, err) into raise tuple from err, which fails the same way. The ChunkedEncodingError branch never had the comma, which is likely why the #323 fix looked complete.

Measured with a stub response whose iter_content raises: before, ReadTimeout and ConnectionError both give TypeError and hand on_abort a tuple; after, they give MastodonReadTimeout / MastodonNetworkError with __cause__ set. ChunkedEncodingError is unchanged in both. Full suite went 522 passed / 18 skipped / 4 xfailed to 525 / 18 / 4 on Python 3.14, macOS.

Not tested: no live stream and no real socket timeout. The new test calls handle_stream directly, and the __stream reconnect consequence is read off the except clause rather than exercised.

Claude Code was used to locate and patch this.

The ReadTimeout and ConnectionError handlers in StreamListener.handle_stream
ended the constructor call with a trailing comma, so `exception` was a 1-tuple.
`raise exception from err` therefore raised

    TypeError: exceptions must derive from BaseException

and on_abort was handed the tuple instead of the exception object its docstring
documents.

This also broke auto-reconnect: Mastodon.__stream catches (AttributeError,
MastodonMalformedEventError, MastodonNetworkError) to decide whether to
reconnect, and TypeError is not in that tuple, so a read timeout or connection
reset terminated the streaming thread.

Reported in halcy#368 and closed as presumed fixed by dropping six; dropping six
turned six.raise_from(tuple, err) into `raise tuple from err`, which fails
identically. The ChunkedEncodingError branch never had the comma.

Adds a test covering all three transport error branches.
@halcy

halcy commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Thank you, good catch, I will have a look at it when I have some more bandwidth

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.

2 participants