Skip to content

kbagent serve --ui crashes on startup on Windows with non-UTF-8 console codepage (UnicodeEncodeError in banner) #522

Description

@papousek-radan

Summary

On Windows with a non-UTF-8 console codepage (e.g. cp1250 on Czech Windows 11), kbagent serve --ui crashes immediately during startup. The startup banner writes box-drawing characters (├─, └─) via sys.stdout.write, which raises UnicodeEncodeError before uvicorn.run is reached — the server never binds.

Environment

  • kbagent v0.72.0 (banner code unchanged on current main / v0.75.0)
  • Windows 11 Enterprise, Czech locale — Python stdout encoding resolves to cp1250
  • Installed via uv tool install

Steps to reproduce

  1. On Windows with a non-UTF-8 console codepage (Czech/Polish/Hungarian locales default to cp1250 for Python's stdout when not in UTF-8 mode), run:
    kbagent serve --ui
    
  2. The process crashes before binding the port.

Actual behavior

UnicodeEncodeError: 'charmap' codec can't encode characters in position ...
  File "...\encodings\cp1250.py", line 19, in encode

raised from the sys.stdout.write(...) banner in src/keboola_agent_cli/commands/serve.py (lines ~235–273). Both the --ui and non-UI banner branches contain ├─ / └─, which cp1250 cannot encode. The same crash would affect any legacy single-byte console encoding.

Expected behavior

The server starts; the banner degrades gracefully on terminals that can't render Unicode.

Workaround

Set PYTHONUTF8=1 before launching (verified working):

set PYTHONUTF8=1
kbagent serve --ui

Suggested fix

Either of:

  1. Reconfigure stdout before printing the banner so encoding errors can't be fatal, e.g.:
    sys.stdout.reconfigure(errors="replace")  # Python 3.7+
    (or wrap in io.TextIOWrapper(..., encoding="utf-8")), or
  2. Fall back to ASCII glyphs (|-, `-) when sys.stdout.encoding can't encode the banner — the same pattern install.sh already uses for its UTF-8 locale check (lines 62–66: Unicode glyphs only under a UTF-8 locale, ASCII otherwise, "so the banner never renders as mojibake on a legacy terminal").

A cheap belt-and-braces variant: wrap the banner write in try/except UnicodeEncodeError and re-emit an ASCII version, so a cosmetic banner can never prevent the server from starting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions