Remove stale rich-markup escapes leaking backslashes into logged warnings
Type of change
- Bug fix (non-breaking change which fixes an issue)
Changes To Core Features:
- Have you added an explanation of what your changes do and why you'd like us to include them?
- Have you written new tests for your core changes, as applicable?
- Have you successfully ran tests with your changes locally?
Defect
FINDING-027 from 0.9.9a1 pre-release testing (cosmetic regression vs 0.9.8, verifier-confirmed): compile-time warnings print literal backslash-escaped brackets, e.g. the event-handler arg-mismatch warning renders as
Warning: Event handler on_submit expects (dict\[str, typing.Any]) -> () but got (dict\[str, str]) -> () ...
where 0.9.8 printed clean dict[str, ...].
Root cause: 0.9.8 built these messages with rich-markup escaping (rich.markup.escape() / .replace("[", "\\[")) and emitted them via the legacy console.* helpers, whose rich Console rendered with markup enabled and consumed the \[ escapes. The 0.9.9 migration to the stdlib logging pipeline kept the escaping, but RichConsoleHandler.emit renders records with markup=False unless a record opts in via extra={"rich": True} (these call sites do not), so the escapes now print literally — in the console sink, the JSON sink, and the full-logging file.
Fix
Drop the stale escaping at every call site that logs through the pipeline without the markup opt-in (all confirmed to use console.* + escaping on the v0.9.8 tag, i.e. all the same migration regression):
reflex_base/event/__init__.py— the arg-mismatch warning from the finding's repro (.replace("[", "\\[")on both type lists)reflex_base/components/component.py— None-to-non-Optional Var deprecation warningreflex_base/vars/base.py— computed var return-type errorreflex_base/event/processor/event_processor.py— event-queue processing error ([txid=...])reflex/state.py— inline computed var type warning and state field type error
Bracketed text now renders verbatim. Markup injection from user-controlled values (type names, event payloads) stays impossible: the sink keeps markup=False, nothing opts into markup rendering. Call sites that do opt in via extra={"rich": True} (e.g. js_runtimes.py, prerequisites.py) correctly keep their escaping and are untouched, as is the deliberate escaping of client-supplied JS error text placed into Exception objects for user-defined frontend exception handlers.
Test plan
- New regression test
tests/units/test_event.py::test_arg_mismatch_warning_renders_brackets_verbatim: reproduces the finding's scenario (handler annotateddict[str, str]bound to theon_submitspecs) through the managed pipeline and asserts the captured rendered output containsexpects (dict[str, typing.Any]) -> () but got (dict[str, str]) -> ()with no backslashes. Fails on unfixed main withdict\[str, typing.Any]in the output; passes with the fix. - New injection-safety test
tests/units/reflex_base/utils/test_log.py::test_warning_with_markup_tags_stays_literal: a warning containing[red]x[/red]renders it literally — neither styled/stripped nor escaped. uv run ruff check .anduv run ruff format .clean;uv run pyright reflex testspasses (0 errors); pyright overreflex_baseshows only a pre-existing warning unrelated to this change.- Scoped suites pass:
tests/units/test_event.py,tests/units/reflex_base/utils/test_log.py,tests/units/reflex_base/event/processor/test_event_processor.py,tests/units/components/test_component.py,tests/units/test_state.py,tests/units/test_var.py,tests/units/vars. (One pre-existing cross-file ordering failure,test_superseding_event_logs_debug_on_cancelwhentest_log.pyruns beforetest_event_processor.pyin the same invocation, reproduces identically on unmodified main and is unrelated.)
🤖 Generated with Claude Code
https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x
Generated by Claude Code