Handle payload-less client_error emits without raising TypeError - #6984
Conversation
python-socketio dispatches events as handler(sid, *data[1:]), so an
emit("client_error") with no payload calls on_client_error(sid) and
raised TypeError during parameter binding -- before the malformed-payload,
unknown-SID, and rate-limit guards ever ran. The exception surfaced as an
asyncio "Task exception was never retrieved" traceback, letting any
connected socket (no valid token needed) flood backend logs at default
loglevel, defeating the anti-abuse hardening the handler carries.
Give data a default of None so the existing isinstance(data, dict) guard
drops the payload-less emit at debug level like any other malformed
payload. Found as FINDING-004 in 0.9.9a1 pre-release testing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
Greptile SummaryThe PR makes
Confidence Score: 5/5The PR appears safe to merge because payload-less client-error events now reach the existing malformed-input guard without changing valid-payload handling. The signature-only behavioral change converts an omitted argument into
|
| Filename | Overview |
|---|---|
| reflex/app.py | Safely defaults the client-error payload to None, which the existing dictionary guard immediately rejects without triggering reporting. |
| tests/units/test_app.py | Adds focused regression coverage confirming payload-less calls neither raise nor produce frontend reports or warning/error console output. |
| news/+client-error-noarg.bugfix.md | Accurately documents the payload-less dispatch failure and the resulting behavior. |
Reviews (1): Last reviewed commit: "Default client_error payload to None so ..." | Re-trigger Greptile
Merging this PR will not alter performance
Comparing Footnotes
|
Type of change
Changes To Core Features:
Defect
FINDING-004 (security-adjacent, medium) from the 0.9.9a1 pre-release testing batch:
EventNamespace.on_client_error(self, sid, data)inreflex/app.pygavedatano default. python-socketio dispatches events ashandler(sid, *data[1:]), so anemit("client_error")with no payload callson_client_error(sid)and raisesTypeError: missing 1 required positional argument: 'data'during parameter binding — before the malformed-payload check, the unknown-SID gate, and the per-SID/per-window rate limiters introduced by #6827 ever run. The exception surfaces via asyncio's "Task exception was never retrieved" handler, so any connected socket — including one that never linked a valid token — could flood the backend logs with tracebacks at default loglevel, unsuppressable via--loglevel, defeating the anti-abuse hardening the handler carries.Fix
Default
datatoNone. The existingisinstance(data, dict)guard then drops a payload-less emit at debug level exactly like any other malformed payload, so every anti-abuse guard runs first. Docstring updated to explain why the default exists; news fragmentnews/+client-error-noarg.bugfix.mdadded.Test plan
tests/units/test_app.py::test_client_error_no_argument_emit_is_ignored(parametrized over known/unknown SID) simulates socketio's no-argument dispatch by callingon_client_error(sid)with nodata, asserting no exception, no report throughfrontend_exception_handler, and no error/warning log records. It fails on unfixed main with the exactTypeErrorfrom the finding and passes with the fix.client_errortests and the fulltests/units/test_app.py(145 tests) pass.uv run ruff check .,uv run ruff format ., anduv run pyright reflex tests(0 errors) are clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
Generated by Claude Code