Skip to content

[codex-app-server Python SDK] UnicodeDecodeError with Popen(text=True) on non-ASCII Windows locales #14311

@sorryhyun

Description

@sorryhyun

What version of the Codex App are you using (From “About Codex” dialog)?

0.114.0

What subscription do you have?

plus

What platform is your computer?

Windows 11

What issue are you seeing?

Summary

AppServerClient.start() uses subprocess.Popen(text=True) without specifying encoding, causing UnicodeDecodeError on Windows systems with non-UTF-8 default encodings (e.g. cp949 for Korean, cp932 for Japanese, cp936 for Chinese).

Environment

  • OS: Windows 11 (Korean locale, default codepage cp949)
  • Python: 3.12+
  • codex-app-server SDK

Error

UnicodeDecodeError: 'cp949' codec can't decode byte 0xed in position 170: illegal multibyte sequence
Turn error: 'cp949' codec can't decode byte 0x80 in position 2460: illegal multibyte sequence

This occurs when the codex subprocess outputs UTF-8 text (e.g. Korean characters in conversation) and Python tries to decode it using the system default encoding (cp949).

What steps can reproduce the bug?

In client.py line 178:

self._proc = subprocess.Popen(
    args,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True,          # <-- uses locale.getpreferredencoding() as encoding
    cwd=self.config.cwd,
    env=env,
    bufsize=1,
)

text=True without an explicit encoding parameter defaults to locale.getpreferredencoding(False), which returns cp949 on Korean Windows, cp932 on Japanese Windows, etc. The codex CLI (Node.js) outputs UTF-8, so any non-ASCII content causes a decode error.

What is the expected behavior?

Suggested Fix

Add encoding="utf-8" to the Popen call:

self._proc = subprocess.Popen(
    args,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True,
    encoding="utf-8",   # <-- explicit UTF-8
    cwd=self.config.cwd,
    env=env,
    bufsize=1,
)

Additional information

Workaround

Downstream users can reconfigure the streams after client.start():

client = AppServerClient(config)
client.start()

proc = client._proc
if proc is not None:
    if proc.stdout and hasattr(proc.stdout, "reconfigure"):
        proc.stdout.reconfigure(encoding="utf-8")
    if proc.stderr and hasattr(proc.stderr, "reconfigure"):
        proc.stderr.reconfigure(encoding="utf-8")
    if proc.stdin and hasattr(proc.stdin, "reconfigure"):
        proc.stdin.reconfigure(encoding="utf-8")

client.initialize()

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingwindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions