You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Message renderer corrupts non-ASCII characters (em-dash, Latvian diacritics) to "?" #5070
Body:
Messages sent via the Buzz CLI that contain non-ASCII Unicode - specifically em-dashes (U+2014) and Latvian accented characters (a/e/u with macrons) - are displayed in the channel as "?" instead of the correct glyph.
Example: an agent message containing the word "buvvalde" (with macron on the u) and an em-dash renders both as "?".
Expected: correct Unicode rendering, or at minimum an encoding warning so senders know characters will be lost.
Likely cause: the message content is being byte-truncated or the renderer is not UTF-8 clean end-to-end (CLI -> relay -> renderer).
Repro: send a message containing an em-dash or an accented Latvian character via the CLI, view it in the channel.
Root cause found (Windows): content piped into buzz messages send --content - is ASCII-mangled by Windows PowerShell 5.1 before the CLI ever sees it — and the event is signed after the corruption, so the ?s are stored permanently on the relay.
TL;DR
Windows PowerShell 5.1 re-encodes anything piped to a native executable using $OutputEncoding, whose default is US-ASCII. Every non-ASCII character (Greek, Latvian diacritics, em-dashes — all of them) becomes a literal ? (0x3F), one per character, ASCII passes through untouched.
buzz messages send --content - reads stdin (strict UTF-8, validate.rs::read_or_stdin) — but the bytes are already 3f 3f 3f … at that point. The CLI then faithfully signs and submits the corrupted content, so it verifies fine and is stored forever.
Passing the same text as an argument (--content "…") is lossless on Windows (argv is UTF-16 end-to-end: PowerShell/cmd → CreateProcessW → Rust args_os()), which is why short/single-line messages work and only multiline/piped ones break. This makes the bug look intermittent or like a regression when it's actually shape-dependent.
This is not a renderer or relay bug — the whole Rust pipeline (buzz-acp → buzz-cli → relay/Postgres) is UTF-8 clean. It also explains why the em-dash in this report became ?: an ANSI-codepage conversion would have preserved it (0x97 in cp1252); only an ASCII conversion kills it.
The same string piped through Git Bash (printf '%s' '…' | od -An -tx1) arrives as perfect UTF-8.
How agents end up on the corrupting path
Two compounding factors, both observed on a real deployment (Buzz Desktop 0.5.16, managed Claude agents on Windows):
crates/buzz-acp/src/base_prompt.md recommends the multiline send pattern printf '…' | buzz messages send --content -. That idiom is safe only in bash. Agents running a PowerShell tool translate it to $body = @'…'@; $body | buzz messages send --content - → corrupted.
On the affected machine, Git Bash failed to resolve the extension-less buzz (only buzz.exe is on PATH; command -v buzz fails while command -v buzz.exe succeeds), so the agent's first attempt via bash died with buzz: command not found and it fell back to the PowerShell pipe. So even agents that prefer the safe path get funneled into the unsafe one.
Verified from the agent transcripts: identical Greek text sent via --content "…" (argv) arrived intact; the same session's here-string + pipe sends arrived as ?????.
Suggested fixes
Docs/prompt (cheap, high impact): in base_prompt.md (and the bundled buzz-cli skill), state that on Windows content must never be piped into buzz from PowerShell; recommend --content "…" as an argument (argv is Unicode-safe, multiline included), or require $OutputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new() before any pipe.
CLI: add --content-file <path> (read raw bytes as UTF-8 straight from disk, no console/pipe encoding in the loop). This gives agents a shell-agnostic safe path for large/multiline content.
CLI (defensive): when stdin content contains runs of ? and zero non-ASCII bytes, print a warning to stderr pointing at this encoding trap (heuristic, but would have made this failure loud instead of silent).
Packaging: ship an extension-less buzz sh-shim alongside buzz.exe (npm-style) so MSYS/Git-Bash command -v buzz always resolves — this keeps agents on the UTF-8-clean bash path.
Workaround for affected users (no rebuild needed)
Create an extension-less wrapper ~/bin/buzz for Git Bash:
Add to your PowerShell profile: $OutputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new()
Optionally add a standing instruction for your agents (e.g. in ~/.buzz/AGENTS.md below the managed markers, which survives upgrades): never pipe content into buzz from PowerShell; pass --content as an argument or use bash.
Already-corrupted messages can't be repaired (they're signed events) — re-send after applying the workaround. Confirmed working on the affected deployment.
Activity
geosalonica commentedon Aug 18, 2026
Root cause found (Windows): content piped into
buzz messages send --content -is ASCII-mangled by Windows PowerShell 5.1 before the CLI ever sees it — and the event is signed after the corruption, so the?s are stored permanently on the relay.TL;DR
$OutputEncoding, whose default is US-ASCII. Every non-ASCII character (Greek, Latvian diacritics, em-dashes — all of them) becomes a literal?(0x3F), one per character, ASCII passes through untouched.buzz messages send --content -reads stdin (strict UTF-8,validate.rs::read_or_stdin) — but the bytes are already3f 3f 3f …at that point. The CLI then faithfully signs and submits the corrupted content, so it verifies fine and is stored forever.--content "…") is lossless on Windows (argv is UTF-16 end-to-end: PowerShell/cmd →CreateProcessW→ Rustargs_os()), which is why short/single-line messages work and only multiline/piped ones break. This makes the bug look intermittent or like a regression when it's actually shape-dependent.This is not a renderer or relay bug — the whole Rust pipeline (buzz-acp → buzz-cli → relay/Postgres) is UTF-8 clean. It also explains why the em-dash in this report became
?: an ANSI-codepage conversion would have preserved it (0x97 in cp1252); only an ASCII conversion kills it.Reproduction (Windows 10, PowerShell 5.1)
The same string piped through Git Bash (
printf '%s' '…' | od -An -tx1) arrives as perfect UTF-8.How agents end up on the corrupting path
Two compounding factors, both observed on a real deployment (Buzz Desktop 0.5.16, managed Claude agents on Windows):
crates/buzz-acp/src/base_prompt.mdrecommends the multiline send patternprintf '…' | buzz messages send --content -. That idiom is safe only in bash. Agents running a PowerShell tool translate it to$body = @'…'@; $body | buzz messages send --content -→ corrupted.buzz(onlybuzz.exeis onPATH;command -v buzzfails whilecommand -v buzz.exesucceeds), so the agent's first attempt via bash died withbuzz: command not foundand it fell back to the PowerShell pipe. So even agents that prefer the safe path get funneled into the unsafe one.Verified from the agent transcripts: identical Greek text sent via
--content "…"(argv) arrived intact; the same session's here-string + pipe sends arrived as?????.Suggested fixes
base_prompt.md(and the bundled buzz-cli skill), state that on Windows content must never be piped intobuzzfrom PowerShell; recommend--content "…"as an argument (argv is Unicode-safe, multiline included), or require$OutputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new()before any pipe.--content-file <path>(read raw bytes as UTF-8 straight from disk, no console/pipe encoding in the loop). This gives agents a shell-agnostic safe path for large/multiline content.?and zero non-ASCII bytes, print a warning to stderr pointing at this encoding trap (heuristic, but would have made this failure loud instead of silent).buzzsh-shim alongsidebuzz.exe(npm-style) so MSYS/Git-Bashcommand -v buzzalways resolves — this keeps agents on the UTF-8-clean bash path.Workaround for affected users (no rebuild needed)
~/bin/buzzfor Git Bash:$OutputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new()~/.buzz/AGENTS.mdbelow the managed markers, which survives upgrades): never pipe content intobuzzfrom PowerShell; pass--contentas an argument or use bash.Already-corrupted messages can't be repaired (they're signed events) — re-send after applying the workaround. Confirmed working on the affected deployment.
buzz-dev-mcp: configure PowerShell UTF-8 pipes