Skip to content

[BUG][Windows] Gateway Telegram error replies crash on non-ASCII exception text #1752

@Dhivya-Bharathy

Description

@Dhivya-Bharathy

[BUG][Windows] Gateway Telegram error replies crash on non-ASCII exception text

Labels: bug, windows, gateway, telegram, encoding


Overview

On Windows, Python's default console encoding is often cp1252 (Windows-1252), not UTF-8. When a gateway Telegram bot hits an error during agent.chat() — API quota exceeded, tool failure, LLM timeout — PraisonAI tries to send the exception text back to the user via reply_text(). If that exception string contains non-ASCII characters (warning symbols, emoji, international text from LLM output), the error handler itself crashes with a charmap encoding error.

The user sees the encoding error instead of the real underlying problem. In a Hermes workforce deployment, the CFO bot appeared broken with:

Error: 'charmap' codec can't encode character '\u26a0' in position 1: character maps to <undefined>

The root cause was OpenAI 429 quota exceeded — but Windows masked it behind a secondary encoding failure.


What the user sees

Error returned in Telegram (what the user actually received)

Error: 'charmap' codec can't encode character '\u26a0' in position 1: character maps to <undefined>

This message appeared twice (duplicate handler invocation or retry). The user had no indication that the real problem was API billing.

Underlying error (in logs — if UTF-8 logging works)

Error code: 429 - {'error': {'message': 'You exceeded your current quota,
please check your plan and billing details...', 'type': 'insufficient_quota'}}

Full failure chain

sequenceDiagram
    participant U as User (Telegram)
    participant G as Gateway handler
    participant API as OpenAI API
    participant Win as Windows cp1252 console

    U->>G: "What is our burn rate?"
    G->>API: agent.chat()
    API-->>G: 429 insufficient_quota

    Note over G: PraisonAI builds error string with ⚠ (U+26A0)
    G->>Win: log or format exception with ⚠
    Win-->>G: UnicodeEncodeError charmap

    G->>U: "Error: 'charmap' codec can't encode..."
    Note over U: User thinks bot code is broken,<br/>not that billing needs fixing
Loading

Why \u26a0 appears

\u26a0 is the warning sign emoji (⚠). PraisonAI's agent/error formatting paths embed warning symbols in exception messages, budget alerts, and tool failure strings. On Linux/macOS with UTF-8 terminals this renders fine. On Windows cp1252:

  • str(e) or f-string formatting touches the console or a cp1252-encoded stream.
  • Python raises: 'charmap' codec can't encode character '\u26a0' in position N.
  • The gateway except block tries reply_text(f"Error: {str(e)}") — which may fail again or send the charmap message to Telegram.

Architecture — encoding layers on Windows

flowchart TB
    subgraph FixedPaths["Partially fixed (other subsystems)"]
        CLI["CLI __main__.py UTF-8 reconfigure"]
        CON["console.py safe print"]
        SK["Skills SKILL.md UTF-8 reads #1695"]
    end

    subgraph BrokenPaths["Still broken (gateway)"]
        GW["gateway/server.py handle_message except"]
        YAML["gateway YAML load open without encoding=utf-8"]
        LOG["logger.error with unicode exception"]
    end

    subgraph Workaround["Deployment workaround"]
        ENV["PYTHONUTF8=1"]
        STD["stdout.reconfigure(encoding=utf-8)"]
    end

    GW --> BrokenPaths
    Workaround -.->|"manual in start_gateway.py"| GW
Loading

CLI --help crash on Windows is tracked separately (#1543). Skills UTF-8 reads were fixed in #1695. Gateway bot error path was not.


Real deployment workaround (should not be required)

Workforce launcher sets before gateway start:

os.environ.setdefault("PYTHONUTF8", "1")
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
sys.stderr.reconfigure(encoding="utf-8", errors="replace")

This reduces console-side crashes but does not fix reply_text() paths that stringify exceptions without sanitization inside PraisonAI itself.


Proposed fix

1. Safe error string helper

def safe_error_message(exc: BaseException, max_len: int = 500) -> str:
    """ASCII-safe error text for Telegram/Discord replies on all platforms."""
    text = str(exc) or type(exc).__name__
    # Strip or replace non-ASCII for transport; preserve meaning
    ...

Use in gateway handle_message except block instead of raw str(e).

2. UTF-8 for all config reads

Gateway YAML loading should use open(path, encoding="utf-8") consistently.

3. Preserve root cause for operator

Telegram user sees: "Error: OpenAI API quota exceeded (429). Check billing."

Logs retain full exception with unicode safely encoded (errors="replace").

4. Document Windows gateway requirement

PraisonAIDocs: set PYTHONUTF8=1 or PYTHONIOENCODING=utf-8 for Windows gateway deployments until fix ships.


Distinction from related issues

Issue Scope
#1543 (open) praisonai --help crashes on Windows — CLI only
#1695 (closed) SKILL.md file reads — skills subsystem
This issue Gateway Telegram reply_text on agent errors — production bot path

Acceptance criteria

  • Gateway Telegram sends readable error reply on Windows when exception contains \u26a0, emoji, or non-Latin text
  • No secondary UnicodeEncodeError / charmap crash in error handler
  • Underlying API errors (429, 401, timeout) surface clearly to user without encoding noise
  • Unit test: mock exception with \u26a0safe_error_message returns sendable ASCII or valid UTF-8
  • Gateway config YAML reads use encoding="utf-8"

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions