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
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
renderQrTerminal(qr, { small: true }) in the WhatsApp channel-login flow produces a final QR-pattern row with ~10× the ANSI-escape-code density of every other row, which can break QR scanning on terminals with strict ANSI parsers, narrow buffers, or limited Unicode font support.
Steps to reproduce
Reproduce using the bundled qrcode library directly, with the same options the WhatsApp login uses (per extensions/whatsapp/src/login.ts:25 → src/media/qr-terminal.ts):
cd<openclaw source clone>
pnpm install # if not already
node -e "const qr = require('qrcode'); qr.toString('https://wa.me/login/2@SAMPLE-TOKEN-1234567890ABCDEF', {type:'terminal', small:true}).then(s => process.stdout.write(s))"
Inspect the last printed line versus any other row.
Expected behavior
Each row uses approximately one set of color escape codes per row. Non-final rows in the same output demonstrate this:
[47m[30m ▄▄▄▄▄▄▄ ▄ ▄ ▄▄▄▄▄ ▄▄ ▄ ▄▄▄▄▄▄▄ [0m
(one open-color sequence, content, one reset).
Actual behavior
The last row has color codes wrapped around every individual cell instead of once per row:
Reproduced on bundled qrcode 1.5.4 (latest as of 2026-05-04, npm view qrcode version). With a 25-cell-wide test QR the last row is 554 characters of mostly ANSI noise vs. ~50 chars per typical row. Bug is consistent across two different input lengths I tested.
OpenClaw version
2026.5.2 (HEAD on main, commit 5b6e552b51)
Operating system
Cross-platform — the bug is in the JS rendering of the QR string itself, not in any specific terminal. Originally noticed on Windows / Git Bash (mintty); reproduces equally in pure Linux node REPLs.
Some narrower terminals with per-line buffer limits.
In all of these cases the rest of the QR may render correctly while the last row is missing or malformed, leaving the QR unscannable without obvious error.
Additional information
Hypothesis on the root cause (offered as analysis, not as observed code from upstream):
With small: true, the qrcode library pairs every two QR-pixel rows into one terminal row using ▀ ▄ █ half-block characters. QR matrix dimensions are always odd (21×21, 25×25, 29×29, …), so the last terminal row contains only an upper-QR-pixel row with no lower partner. The library appears to fall into a per-cell color-emission path for this final partial row instead of the per-row-optimized path used for all other rows.
Mitigation options for openclaw (ordered by simplicity):
(A) One-liner: change small: opts.small ?? true → small: opts.small ?? false in src/media/qr-terminal.ts:8. Produces a visually larger QR (full-block chars) but with consistent escape density across all rows, eliminating the broken-last-row mode entirely.
(B) Config-gated: add an OPENCLAW_QR_FORMAT=small|large env var so users on terminals that handle the dense escapes fine keep the compact rendering, and users on broken terminals can opt out.
Related work: open PR #72762 adds WSL-specific font guidance to the CLI — that addresses the user-visible symptom on one platform, while this issue describes the underlying root cause and a more direct fix path.
I'm happy to prepare a PR for option A or B if maintainers indicate the preferred direction. Investigation was AI-assisted; happy to redirect or close if a different approach is preferred.
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
renderQrTerminal(qr, { small: true })in the WhatsApp channel-login flow produces a final QR-pattern row with ~10× the ANSI-escape-code density of every other row, which can break QR scanning on terminals with strict ANSI parsers, narrow buffers, or limited Unicode font support.Steps to reproduce
Reproduce using the bundled
qrcodelibrary directly, with the same options the WhatsApp login uses (perextensions/whatsapp/src/login.ts:25→src/media/qr-terminal.ts):Inspect the last printed line versus any other row.
Expected behavior
Each row uses approximately one set of color escape codes per row. Non-final rows in the same output demonstrate this:
(one open-color sequence, content, one reset).
Actual behavior
The last row has color codes wrapped around every individual cell instead of once per row:
Reproduced on bundled
qrcode1.5.4 (latest as of 2026-05-04,npm view qrcode version). With a 25-cell-wide test QR the last row is 554 characters of mostly ANSI noise vs. ~50 chars per typical row. Bug is consistent across two different input lengths I tested.OpenClaw version
2026.5.2 (HEAD on
main, commit5b6e552b51)Operating system
Cross-platform — the bug is in the JS rendering of the QR string itself, not in any specific terminal. Originally noticed on Windows / Git Bash (mintty); reproduces equally in pure Linux
nodeREPLs.Install method
source clone (
git clone openclaw/openclaw && pnpm install)Model
NOT_ENOUGH_INFO (not model-related)
Provider / routing chain
NOT_ENOUGH_INFO
Additional provider/model setup details
NOT_ENOUGH_INFO
Logs, screenshots, and evidence
Side-by-side from the same QR rendering (raw output of the reproduction command):
Typical row (~50 chars):
Last row (~554 chars):
Impact and severity
Severity: Medium — silent or near-silent failure mode that breaks scannability rather than crashing. Affects users on:
In all of these cases the rest of the QR may render correctly while the last row is missing or malformed, leaving the QR unscannable without obvious error.
Additional information
Hypothesis on the root cause (offered as analysis, not as observed code from upstream):
With
small: true, theqrcodelibrary pairs every two QR-pixel rows into one terminal row using▀ ▄ █half-block characters. QR matrix dimensions are always odd (21×21, 25×25, 29×29, …), so the last terminal row contains only an upper-QR-pixel row with no lower partner. The library appears to fall into a per-cell color-emission path for this final partial row instead of the per-row-optimized path used for all other rows.Mitigation options for openclaw (ordered by simplicity):
small: opts.small ?? true→small: opts.small ?? falseinsrc/media/qr-terminal.ts:8. Produces a visually larger QR (full-block chars) but with consistent escape density across all rows, eliminating the broken-last-row mode entirely.OPENCLAW_QR_FORMAT=small|largeenv var so users on terminals that handle the dense escapes fine keep the compact rendering, and users on broken terminals can opt out.Related work: open PR #72762 adds WSL-specific font guidance to the CLI — that addresses the user-visible symptom on one platform, while this issue describes the underlying root cause and a more direct fix path.
I'm happy to prepare a PR for option A or B if maintainers indicate the preferred direction. Investigation was AI-assisted; happy to redirect or close if a different approach is preferred.