Skip to content

[BUG][Windows][Regression] bot_gateway_e2e.py still crashes cp1252 stdout after gateway #3475 fix #3499

Description

@Dhivya-Bharathy

[BUG][Windows][Regression] bot_gateway_e2e.py still crashes cp1252 stdout after gateway #3475 fix

Metadata

Field Value
Repository https://github.com/MervinPraison/PraisonAI
Labels bug, windows, praisonai-bot, e2e, developer-experience, regression
Severity Medium — live browser E2E still unusable on default Windows console; masks Playwright install hint
Component e2e-platform-audit/bot_gateway_e2e.py (Report.add, browser probe block)
Related (closed) #3430, #3475
Reverification date 2026-07-29
Commit tested e22dc0d17 (main)

Executive summary

Follow-up issue #3475 hardened praisonai_bot/gateway/unicode_utils.py (maps U+2551 box-drawing chars from Playwright stderr) and closed. However the E2E harness that developers run locally — e2e-platform-audit/bot_gateway_e2e.pywas not updated and still calls bare print() on failure details containing Playwright's framed playwright install banner.

On Windows with default cp1252 console encoding (PYTHONUTF8 unset), reverification 2026-07-29 shows:

  • 10/14 live checks PASS (gateway, MCP, code)
  • Browser control (playwright headless) FAIL — real error captured in JSON: playwright install
  • Browser control via bot message FAIL — console shows 'charmap' codec can't encode character '\u2551' instead of actionable hint

This is a regression of incomplete fix scope: gateway server paths are safe; audit script paths are not.


Environment

Field Value
OS Windows 10 (10.0.19045)
Shell PowerShell (legacy conhost)
Python 3.11.15 (uv) / 3.13.2
Console encoding cp1252 (PYTHONUTF8 unset deliberately)
PraisonAI commit e22dc0d17
praisonai-bot 0.0.42
praisonai-browser 0.0.9
Playwright Python package Installed
Playwright browser binaries Not installed (triggers install banner)
OpenAI API Present

Step-by-step reproduction

git clone https://github.com/MervinPraison/PraisonAI.git
cd PraisonAI
pip install -e ".[all]"
# Deliberately skip: playwright install chromium

Remove-Item Env:PYTHONUTF8 -ErrorAction SilentlyContinue
$env:OPENAI_API_KEY = "<your-key>"
$env:PRAISONAI_AUTO_APPROVE = "true"

python e2e-platform-audit/bot_gateway_e2e.py --live-only

Expected behavior

  • Browser checks FAIL with ASCII-readable message: Please run: playwright install
  • Harness completes; JSON report and console agree on root cause
  • Other live checks (gateway, MCP, code) PASS

Actual behavior (2026-07-29)

  • Gateway, MCP, code checks PASS
  • Console:
[FAIL] browser control via bot message — 'charmap' codec can't encode character '\u2551' in position 62: character maps to <undefined>
=== Done: 4 failed ===
  • JSON report (UTF-8) preserves real Playwright stderr with \u2551 box chars — console lies, JSON tells truth

Full terminal evidence

Live E2E console (2026-07-29, commit e22dc0d17)

=== PraisonAI Bot Gateway E2E ===

[OK] import praisonai_bot — 0.0.42
[OK] import praisonai_code — 0.0.57
[OK] import praisonai_browser — 0.0.9
[OK] import praisonai_mcp — 0.0.9
[OK] import praisonai_sandbox — 0.0.7
[OK] OPENAI_API_KEY — present
[FAIL] docker sandbox live execute — docker daemon not reachable
[OK] gateway startup (praisonai-bot) — 127.0.0.1:18765
[OK] mcp gateway /mcp endpoint — agent tool listed (1 tools)
[OK] mcp tools/call via bot gateway — response len=10
[OK] praisonai-code execute via bot message — marker found
[FAIL] sandbox exec via bot message — It seems there was no output for the command...
[FAIL] browser control via bot message — 'charmap' codec can't encode character '\u2551'...

=== Done: 4 failed ===
Report: .../report_20260729_141007.json

JSON report excerpt (browser checks)

{
  "name": "browser control (playwright headless)",
  "status": "FAIL",
  "detail": "updated.       \u2551\r\n\u2551 Please run the following command to download new browsers: \u2551\r\n\u2551     playwright install                              ",
  "duration_s": 24.52
},
{
  "name": "browser control via bot message",
  "status": "FAIL",
  "detail": "'charmap' codec can't encode character '\\u2551' in position 62: character maps to <undefined>",
  "duration_s": 24.52
}

Interactive analysis

Fix scope gap (#3475 vs E2E harness)

flowchart TD
    subgraph fixed [Fixed in #3475]
        GW[WebSocketGateway error handlers]
        UU[unicode_utils.sanitize_for_console]
        GW --> UU
    end

    subgraph broken [Still broken]
        E2E[bot_gateway_e2e.py]
        ADD[Report.add bare print]
        PROBE[_playwright_headless_probe]
        E2E --> PROBE
        PROBE -->|RuntimeError with U+2551| ADD
        ADD -->|cp1252 stdout| CRASH[UnicodeEncodeError]
    end

    fixed -.->|not wired| broken
Loading

Failure sequence

sequenceDiagram
    participant E2E as bot_gateway_e2e.py
    participant PW as Playwright subprocess
    participant R as Report.add
    participant Out as stdout cp1252

    E2E->>PW: chromium.launch headless probe
    PW-->>E2E: stderr with U+2551 install banner
    E2E->>E2E: Check FAIL detail = RuntimeError text
    E2E->>R: add(FAIL, detail contains ║)
    R->>Out: print(f"[FAIL] ... {detail}")
    Out-->>R: UnicodeEncodeError U+2551
    R-->>E2E: outer except records charmap error
    Note over E2E: Developer never sees playwright install on console
Loading

Decision tree for developer diagnosis

flowchart TD
    A[browser control FAIL on Windows] --> B{Read JSON report or console?}
    B -->|Console only| C[See charmap U+2551 error]
    C --> D[Misdiagnose as encoding bug]
    B -->|JSON report| E[See playwright install hint]
    E --> F[Run playwright install chromium]
    F --> G{Browsers installed?}
    G -->|Yes| H[Re-run E2E — browser should PASS]
    G -->|No| I[Still FAIL until install]
    D --> J[Fix: wire E2E to unicode_utils]
    J --> E
Loading

Root cause analysis

Layer 1 — Playwright browsers missing (environment)

_playwright_headless_probe() at lines 385–408 launches Chromium in subprocess. When browsers not installed, Playwright stderr includes boxed banner with U+2551 () characters.

Layer 2 — E2E harness not using gateway sanitization

unicode_utils.py (post-#3475) explicitly maps \u2551 to space for Playwright banners:

# src/praisonai-bot/praisonai_bot/gateway/unicode_utils.py
'\u2550': ' ', '\u2551': ' ',   # DOUBLE HORIZONTAL/VERTICAL -> space

But bot_gateway_e2e.py does not import or call this module.

Layer 3 — Encoding-unsafe Report.add()

# e2e-platform-audit/bot_gateway_e2e.py lines 60-63
def add(self, check: Check) -> None:
    self.checks.append(check)
    icon = {"PASS": "OK", "FAIL": "FAIL", "SKIP": "SKIP"}.get(check.status, "?")
    print(f"[{icon}] {check.name}" + (f" — {check.detail}" if check.detail else ""))

Bare print() encodes to cp1252 on Windows → crash when check.detail contains \u2551.

Layer 4 — PYTHONUTF8 setdefault does not help

Line 30: os.environ.setdefault("PYTHONUTF8", "1") — on many Windows Python builds this does not reconfigure an already-initialized stdout when console is cp1252. Audit intentionally runs without forcing UTF-8 to reproduce developer default.

Layer 5 — Outer exception handler masks probe error

Browser block catches exceptions from report.add() itself, recording the encoding error as the browser bot message failure — same class of bug as original #3430.


Comparison: PraisonAIUI pattern (already fixed)

PraisonAIUI added examples/python/_shared/console.py with safe_print() and ASCII fallbacks for gateway examples (#235). PraisonAI E2E harness should mirror:

from praisonai_bot.gateway.unicode_utils import sanitize_for_console, safe_print

def add(self, check: Check) -> None:
    self.checks.append(check)
    icon = {"PASS": "OK", "FAIL": "FAIL", "SKIP": "SKIP"}.get(check.status, "?")
    msg = f"[{icon}] {check.name}" + (f" — {check.detail}" if check.detail else "")
    safe_print(sanitize_for_console(msg))

Proposed fixes

Option A — Reuse unicode_utils (recommended)

Import sanitize_for_console / safe_print from praisonai_bot.gateway.unicode_utils in bot_gateway_e2e.py and use in Report.add() and all top-level print() calls.

Option B — Sanitize probe errors before Check

from praisonai_bot.gateway.unicode_utils import sanitize_for_console

err = (stderr or b"").decode(errors="replace").strip()
raise RuntimeError(sanitize_for_console(err[-400:]))

Option C — ASCII-only Playwright preflight

Before probe, run python -m playwright install --dry-run or check browser path; skip probe with clear ASCII message if missing.

Option D — CI gate

Add Windows cp1252 job running bot_gateway_e2e.py --live-only without PYTHONUTF8.


Test plan

Step Action Expected
1 Run E2E on Windows cp1252 without Playwright browsers Console shows playwright install, not charmap error
2 playwright install chromium + re-run Browser checks PASS
3 Run with PYTHONUTF8=1 Same ASCII-safe output
4 Gateway unicode unit tests Still pass (31 tests)
5 JSON report detail Matches console (both sanitized)

Automated test to add

def test_report_add_survives_box_drawing_detail():
    from bot_gateway_e2e import Report, Check
    r = Report()
    detail = "Please run: playwright install " + "\u2551" * 4
    r.add(Check("probe", "FAIL", detail))  # must not raise

Acceptance criteria

  1. bot_gateway_e2e.py --live-only never raises UnicodeEncodeError on cp1252 Windows console
  2. When Playwright browsers missing, console shows actionable playwright install hint
  3. Report.add() uses same sanitization as gateway unicode_utils
  4. JSON report and console agree on failure root cause
  5. No regression on Linux/macOS UTF-8 terminals

Appendix: Non-browser failures in same run (context)

Check Status Notes
docker sandbox live execute FAIL Docker daemon not running — env, not product bug
sandbox exec via bot message FAIL LLM did not return E2E_SANDBOX_OK — see separate draft PAI-007

Appendix: Files to change

File Change
e2e-platform-audit/bot_gateway_e2e.py safe_print + sanitize_for_console in Report.add and main prints
e2e-platform-audit/tests/test_e2e_console.py New — cp1252-safe detail rendering
AGENTS.md / E2E docs Note: run playwright install before browser live checks

Appendix: Related closed issues

This issue tracks the remaining scope for complete Windows browser E2E developer experience.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaudeAuto-trigger Claude analysisdocumentationImprovements or additions to documentation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions