{"record":{"id":"8266a8ce006c7a4f","repo":"Hmbown/CodeWhale","slug":"harmony-uiinput-text-must-be-printable-ascii-on-this-backend","errorCode":null,"errorMessage":"harmony uiInput text must be printable ASCII on this backend","messagePattern":"harmony uiInput text must be printable ASCII on this backend","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/harmonyos.mjs","lineNumber":17,"sourceCode":"// HarmonyOS backend — drives a device/emulator through `hdc` (HarmonyOS\n// Device Connector) plus the on-device `uitest` and `snapshot_display` tools.\n// Observation: `uitest dumpLayout` (the accessibility-tree equivalent).\n// Input:       `uitest uiInput` (click / swipe / inputText / keyEvent).\n// Stills:      `snapshot_display`. Video: no CLI screen recorder exists on\n//              current HarmonyOS shells, so recording is an honest\n//              snapshot-series mode muxed with ffmpeg on the host.\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { run, runOk, ExecError, tryJson, have, currentSignal, throwIfAborted } from \"../exec.mjs\";\n\nconst DEVICE_TMP = \"/data/local/tmp/cu\";\n\nfunction escDeviceText(s) {\n  if (/[^\\x20-\\x7E]/.test(s)) throw new ExecError(\"harmony uiInput text must be printable ASCII on this backend\");\n  return `'${String(s).replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction jpegSize(buf) {\n  // Minimal JPEG SOF parser — enough to learn the panel size of a snapshot.\n  let i = 2;\n  while (i + 9 < buf.length) {\n    if (buf[i] !== 0xff) { i++; continue; }\n    const marker = buf[i + 1];\n    if (marker >= 0xc0 && marker <= 0xcf && ![0xc4, 0xc8, 0xcc].includes(marker)) {\n      return { h: buf.readUInt16BE(i + 5), w: buf.readUInt16BE(i + 7) };\n    }\n    i += 2 + buf.readUInt16BE(i + 2);\n  }\n  return null;\n}\n\nexport function parseBounds(b) {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/harmonyos.mjs#L1-L35","documentation":"HarmonyOS's uiInput path can only deliver printable ASCII text; escDeviceText throws this ExecError when the string contains any character outside \\x20-\\x7E. This prevents silently dropping or corrupting non-ASCII characters (quotes are still escaped separately).","triggerScenarios":"Calling uiInput / type_text with text containing Unicode letters, emoji, curly quotes, accented characters, tabs, newlines, or other control characters on the harmonyos backend.","commonSituations":"Typing internationalized text (CJK, Cyrillic, accents), copy-pasting smart quotes from word processors, or embedding line breaks into form fields on HarmonyOS devices.","solutions":["Sanitize or transliterate the string to printable ASCII before passing it (e.g. strip or replace non-ASCII characters).","For non-ASCII content, use the clipboard backend instead: write_clipboard the text, then paste.","Catch the ExecError and surface it to the caller rather than sending the raw string to the device."],"exampleFix":"// before\nawait backend.ui_input({ text: 'café ☕' });\n// after\nconst ascii = 'café ☕'.replace(/[^\\x20-\\x7E]/g, '');\nif (ascii) await backend.ui_input({ text: ascii });\nelse await backend.write_clipboard({ text: 'café ☕' }); // then paste","handlingStrategy":"try-catch","validationCode":"if (/[^\\x20-\\x7E]/.test(text)) throw new TypeError('text must be printable ASCII for harmony uiInput');","typeGuard":"const isPrintableAscii = (s) => typeof s === 'string' && !/[^\\x20-\\x7E]/.test(s);","tryCatchPattern":"try { await backend.ui_input({ text }); } catch (e) { if (String(e.message).includes('printable ASCII')) { await backend.write_clipboard({ text }); await backend.perform_action(pasteAction); } else throw e; }","preventionTips":["Sanitize or transliterate text to ASCII before device input on HarmonyOS.","Route non-ASCII text through the clipboard/paste path.","Unit-test input helpers with emoji, accents, and newlines."],"tags":["harmonyos","encoding","ascii","input"],"backgroundTag":"invalid-argument-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}