{"record":{"id":"8d2e3ea62c3d8622","repo":"Hmbown/CodeWhale","slug":"hdc-shell-args-0-exited-r-code-r-stderr-r-stdout-trim-slice","errorCode":null,"errorMessage":"hdc shell ${args[0]} exited ${r.code}: ${(r.stderr || r.stdout).trim().slice(0, 300)}","messagePattern":"hdc shell (.+?) exited (.+?): (.+?)","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/harmonyos.mjs","lineNumber":75,"sourceCode":"}\n\n/** Coordinate clicks on this backend are always raw pointer events; strategy=\"a11y\" must fail closed rather than silently degrade. */\nfunction assertEventStrategy(strategy) {\n  if (strategy != null && strategy !== \"auto\" && strategy !== \"event\") {\n    throw new ExecError(`strategy \"${strategy}\" is macOS-only; this backend dispatches coordinate clicks as raw pointer events — use an element target for a semantic action`);\n  }\n}\n\nfunction rejectAppSelectors(args) {\n  if ([\"app_ref\", \"window_id\", \"windowIndex\"].some(key => Object.hasOwn(args, key))) throw Object.assign(new ExecError(\"HarmonyOS cannot select an app or window for observation or element actions; explicit selectors are unsupported\"), { code: \"unsupported_selector\" });\n}\n\nexport function create({ exec }) {\n  const shell = (args, opts = {}) => exec.shell(args, { timeoutMs: 20_000, ...opts });\n\n  async function deviceOut(args, opts = {}) {\n    const r = await shell(args, opts);\n    if (r.code !== 0) throw new ExecError(`hdc shell ${args[0]} exited ${r.code}: ${(r.stderr || r.stdout).trim().slice(0, 300)}`, r);\n    return r.stdout;\n  }\n\n  async function snapshot(localPath) {\n    const remote = `${DEVICE_TMP}-${crypto.randomBytes(3).toString(\"hex\")}.jpeg`;\n    await deviceOut([\"snapshot_display\", \"-f\", remote], { timeoutMs: 25_000 });\n    try {\n      await exec.pullFile(remote, localPath, { timeoutMs: 30_000 });\n    } finally {\n      await shell([\"rm\", \"-f\", remote]).catch(() => {});\n    }\n    return localPath;\n  }\n\n  async function dumpLayout() {\n    const remote = `${DEVICE_TMP}-layout.json`;\n    await deviceOut([\"uitest\", \"dumpLayout\", \"-p\", remote], { timeoutMs: 40_000 });\n    let data;","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/harmonyos.mjs#L57-L93","documentation":"deviceOut wraps `hdc shell` invocations and throws this ExecError when the hdc command exits non-zero, embedding the command name, exit code, and up to 300 chars of stderr/stdout. It surfaces device-side command failures from the HarmonyOS computer-use backend.","triggerScenarios":"Any hdc shell call whose process exits non-zero — e.g. `hdc shell snapshot_display -f <path>` failing when the device is locked, `bm dump -a` when the bundle manager errors, or uitest commands failing on an unexpected UI state.","commonSituations":"Device disconnected or unauthorized (hdc target offline), screen locked so snapshot_display fails, DEVICE_TMP not writable, HarmonyOS build lacking a subcommand, or a stale hdc daemon.","solutions":["Read the embedded stderr/stdout snippet for the device-side cause and fix it (unlock the screen, free storage, etc.).","Run `hdc list targets` to confirm the device is connected and authorized; restart with `hdc kill` / reconnect.","Retry the operation — transient device/daemon hiccups commonly cause one-off non-zero exits.","Catch the ExecError and treat it as a backend failure, falling back to re-observation."],"exampleFix":"try {\n  const out = await backend.snapshot('/tmp/shot.jpeg');\n} catch (e) {\n  // e.message e.g. 'hdc shell snapshot_display exited 1: ...'\n  console.error('device command failed:', e.message);\n  await hdcReconnect(); // hdc kill; hdc list targets\n}","handlingStrategy":"try-catch","validationCode":"const targets = await exec.shell(['list', 'targets']); // confirm a connected device before issuing shell commands","typeGuard":"null","tryCatchPattern":"try { const out = await deviceOut(['snapshot_display', '-f', remote]); } catch (e) { if (String(e.message).startsWith('hdc shell')) { log(e.message); await reconnectHdc(); /* retry once */ } else throw e; }","preventionTips":["Check `hdc list targets` before batch operations.","Unlock the device screen before snapshot/uitest commands.","Parse the embedded stderr snippet rather than treating all failures alike.","Add retries with backoff for transient device errors."],"tags":["harmonyos","hdc","command-failed","device"],"backgroundTag":"command-not-found","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T21:17:16.096Z"}