Fix UnicodeEncodeError on startup when stdio uses a non-UTF-8 encoding - #2561
Open
LHMQ878 wants to merge 1 commit into
Open
Fix UnicodeEncodeError on startup when stdio uses a non-UTF-8 encoding#2561LHMQ878 wants to merge 1 commit into
LHMQ878 wants to merge 1 commit into
Conversation
The welcome banner uses box-drawing glyphs (U+2590 and friends) and status messages use U+2713. On Windows the standard streams default to the system locale encoding (e.g. GBK/cp936), which cannot represent them, so the first console write raised UnicodeEncodeError and the CLI died before starting. Reconfigure stdout/stderr to UTF-8 when the shell console is set up. Forcing UTF-8 preserves the glyphs, whereas errors='replace' alone on a multibyte locale codec mangles them into partial-byte garbage. Fixes MoonshotAI#1436
This was referenced Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1436
Problem
On Windows, launching
kimifrom Git Bash dies immediately:▐is▐, from the welcome banner logo inui/shell/__init__.py:The banner is rendered through the shared
consolesingleton insrc/kimi_cli/ui/shell/console.py, which inherits whatever encoding the standard streams have. On Windows those default to the system locale encoding (GBK/cp936 on Chinese installs), which cannot represent the box-drawing glyphs, so the very first console write raisesUnicodeEncodeErrorand the CLI exits before it starts.The same singleton also prints
✓(U+2713) inui/shell/oauth.pyandui/shell/setup.py, so logout and setup were exposed to the identical failure.Fix
Reconfigure
sys.stdout/sys.stderrto UTF-8 when the shell console module is initialized.I first tried leaving the locale codec in place and only adding
errors="replace". That stops the crash but renders the banner as partial-byte garbage (?��?��?����), because GBK is multibyte and replacement happens per unencodable character. Forcing UTF-8 keeps the glyphs intact, and I verified on a GBK-default Git Bash that a UTF-8 byte stream displays▐█▛█▛█▌correctly.errors="replace"is kept as a last resort for anything UTF-8 still can't carry (e.g. lone surrogates).Streams that don't expose
reconfigure(), or that reject it (detached/closed), are skipped rather than failing startup.Verification
Environment: Windows 11, Git Bash,
sys.stdout.encoding == 'gbk',locale.getpreferredencoding() == 'cp936'— i.e. the configuration from the report.UnicodeEncodeError: 'gbk' codec can't encode character '▐'.stdout.encodingbecomesutf-8, and both the banner panel and the✓message render correctly, in a terminal and with stdout redirected to a file.tests/ui/test_console_encoding.py(6 tests, all passing): reconfiguration of both streams, tolerance of streams withoutreconfigure(), tolerance ofOSError/ValueErrorfrom it, plus a guard asserting the banner glyphs genuinely aren't GBK-encodable so the premise can't silently rot.ruff checkandruff format --checkpass on both changed files.Note on overlap with #2560
I have a separate PR (#2560) fixing
Fixes #2532, the same class of bug inutils/server.py'sprint_banner, which covers thekimi webandkimi visstartup paths. That one uses plainprint(), so it needed a different fix. This PR covers the interactive shell path and is independent — neither depends on the other, and they touch different files.