Hmbown/CodeWhale · error · ExecError

harmony uiInput text must be printable ASCII on this backend

Error message

harmony uiInput text must be printable ASCII on this backend

What it means

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).

Solutions

  1. Sanitize or transliterate the string to printable ASCII before passing it (e.g. strip or replace non-ASCII characters).
  2. For non-ASCII content, use the clipboard backend instead: write_clipboard the text, then paste.
  3. Catch the ExecError and surface it to the caller rather than sending the raw string to the device.

Example fix

// before
await backend.ui_input({ text: 'café ☕' });
// after
const ascii = 'café ☕'.replace(/[^\x20-\x7E]/g, '');
if (ascii) await backend.ui_input({ text: ascii });
else await backend.write_clipboard({ text: 'café ☕' }); // then paste
Defensive patterns

Strategy: try-catch

Validate before calling

if (/[^\x20-\x7E]/.test(text)) throw new TypeError('text must be printable ASCII for harmony uiInput');

Type guard

const isPrintableAscii = (s) => typeof s === 'string' && !/[^\x20-\x7E]/.test(s);

Try / catch

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; }

Prevention

When it happens

Trigger: Calling uiInput / type_text with text containing Unicode letters, emoji, curly quotes, accented characters, tabs, newlines, or other control characters on the harmonyos backend.

Common situations: Typing internationalized text (CJK, Cyrillic, accents), copy-pasting smart quotes from word processors, or embedding line breaks into form fields on HarmonyOS devices.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/8266a8ce006c7a4f. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/backends/harmonyos.mjs:17

// HarmonyOS backend — drives a device/emulator through `hdc` (HarmonyOS
// Device Connector) plus the on-device `uitest` and `snapshot_display` tools.
// Observation: `uitest dumpLayout` (the accessibility-tree equivalent).
// Input:       `uitest uiInput` (click / swipe / inputText / keyEvent).
// Stills:      `snapshot_display`. Video: no CLI screen recorder exists on
//              current HarmonyOS shells, so recording is an honest
//              snapshot-series mode muxed with ffmpeg on the host.
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import crypto from "node:crypto";
import { run, runOk, ExecError, tryJson, have, currentSignal, throwIfAborted } from "../exec.mjs";

const DEVICE_TMP = "/data/local/tmp/cu";

function escDeviceText(s) {
  if (/[^\x20-\x7E]/.test(s)) throw new ExecError("harmony uiInput text must be printable ASCII on this backend");
  return `'${String(s).replace(/'/g, `'\\''`)}'`;
}

function jpegSize(buf) {
  // Minimal JPEG SOF parser — enough to learn the panel size of a snapshot.
  let i = 2;
  while (i + 9 < buf.length) {
    if (buf[i] !== 0xff) { i++; continue; }
    const marker = buf[i + 1];
    if (marker >= 0xc0 && marker <= 0xcf && ![0xc4, 0xc8, 0xcc].includes(marker)) {
      return { h: buf.readUInt16BE(i + 5), w: buf.readUInt16BE(i + 7) };
    }
    i += 2 + buf.readUInt16BE(i + 2);
  }
  return null;
}

export function parseBounds(b) {

View on GitHub (pinned to 73e0f67d83)