From 70da14db90ba50c2346b7364584f14ea539f2cac Mon Sep 17 00:00:00 2001 From: Tummalapally Sai Aakash Date: Sun, 12 Jul 2026 20:17:05 +0530 Subject: [PATCH] fix(events): prevent UnicodeEncodeError crash on non-UTF-8 consoles ConsoleFormatter builds a rich.Console around sys.stdout without guarding its encoding. On Windows terminals using a legacy codepage (cp1252), printing emoji panel titles (e.g. Flow Started, Flow Method Running) raises UnicodeEncodeError inside the sync event handlers. The event bus swallows the exception and prints an error line instead, so every Flow event silently fails to render and spams "[CrewAIEventsBus] Sync handler error ..." for the entire run. This is the same root cause behind several previously closed issues (#3062, #2715, #2708, #823, #772, #755, #713, #665, #603) - each was patched around a specific emoji/message rather than fixed at the source, so it keeps recurring as new emoji panels are added. Reconfigure the underlying stream to use errors="replace" so unencodable characters degrade to "?" instead of crashing. Co-authored-by: Cursor --- .../crewai/events/utils/console_formatter.py | 5 ++++ .../test_console_formatter_encoding.py | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 lib/crewai/tests/utilities/test_console_formatter_encoding.py diff --git a/lib/crewai/src/crewai/events/utils/console_formatter.py b/lib/crewai/src/crewai/events/utils/console_formatter.py index 858dde0acc..4d3358f6eb 100644 --- a/lib/crewai/src/crewai/events/utils/console_formatter.py +++ b/lib/crewai/src/crewai/events/utils/console_formatter.py @@ -41,6 +41,11 @@ class ConsoleFormatter: def __init__(self, verbose: bool = False): self.console = Console(width=None) + if hasattr(self.console.file, "reconfigure"): + try: + self.console.file.reconfigure(errors="replace") + except Exception: # noqa: S110 - best-effort; stream may not support reconfigure + pass self.verbose = verbose self._streaming_live: Live | None = None self._is_streaming: bool = False diff --git a/lib/crewai/tests/utilities/test_console_formatter_encoding.py b/lib/crewai/tests/utilities/test_console_formatter_encoding.py new file mode 100644 index 0000000000..6e76772cb5 --- /dev/null +++ b/lib/crewai/tests/utilities/test_console_formatter_encoding.py @@ -0,0 +1,25 @@ +import io + +from rich.text import Text + +from crewai.events.utils.console_formatter import ConsoleFormatter + + +class TestConsoleFormatterEncoding: + """Regression tests: emoji panel titles must not crash on non-UTF-8 streams (e.g. Windows cp1252 console).""" + + def test_reconfigures_stream_errors_to_replace(self): + formatter = ConsoleFormatter() + + assert formatter.console.file.errors == "replace" + + def test_emoji_panel_does_not_raise_on_cp1252_stream(self): + cp1252_stream = io.TextIOWrapper( + io.BytesIO(), encoding="cp1252", write_through=True + ) + formatter = ConsoleFormatter() + formatter.console.file = cp1252_stream + if hasattr(cp1252_stream, "reconfigure"): + cp1252_stream.reconfigure(errors="replace") + + formatter.print_panel(Text("x"), "🌊 Flow Started", "blue", is_flow=True)