{"record":{"id":"0fb22515f209cf28","repo":"Hmbown/CodeWhale","slug":"powershell-did-not-return-json-r-stderr-out-trim-slice-0-300","errorCode":null,"errorMessage":"powershell did not return JSON: ${(r.stderr || out).trim().slice(0, 300)}","messagePattern":"powershell did not return JSON: (.+?)","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/win32.mjs","lineNumber":199,"sourceCode":"    if (r.aborted) throw Object.assign(new ExecError(\"computer request cancelled\", r), { code: \"cancelled\" });\n    if (r.timedOut) throw new ExecError(`powershell timed out after ${o.timeoutMs ?? 25_000}ms`, r);\n    if (r.code !== 0) {\n      const raw = (r.stderr || r.stdout).trim();\n      // EncodedCommand serializes errors as CLIXML; surface the error strings,\n      // not a truncated XML/progress header that conceals the actual failure.\n      const messages = [...raw.matchAll(/<S S=\"Error\">([\\s\\S]*?)<\\/S>/g)].map(m => m[1]\n        .replace(/_x([0-9A-Fa-f]{4})_/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))\n        .replace(/&lt;/g, \"<\").replace(/&gt;/g, \">\").replace(/&quot;/g, '\"').replace(/&apos;/g, \"'\").replace(/&amp;/g, \"&\"));\n      throw new ExecError(`powershell.exe exited ${r.code}: ${(messages.join(\"\") || raw).slice(0, 1600)}`, r);\n    }\n    return r;\n  }\n\n  async function psJson(script, o = {}) {\n    const r = await psOk(script, o);\n    const out = r.stdout.trim();\n    const j = tryJson(out, null);\n    if (!j) throw new ExecError(`powershell did not return JSON: ${(r.stderr || out).trim().slice(0, 300)}`, r);\n    return j;\n  }\n\n  let lastRaster = null;\n  let activeDisplay = null;\n  const heldButtons = new Set();\n  const heldKeys = new Set();\n\n  async function releaseInput({ buttons = [...heldButtons], keys = [...heldKeys] } = {}) {\n    buttons = buttons.filter((button) => heldButtons.has(button));\n    keys = keys.filter((key) => heldKeys.has(key));\n    if (!buttons.length && !keys.length) return;\n    const releases = [\n      ...buttons.map((button) => `[User32]::mouse_event([User32]::${button}UP, 0, 0, 0, [UIntPtr]::Zero);`),\n      ...keys.reverse().map((vk) => `[User32]::SendKey(${vk}, 2);`),\n    ];\n    await withSignal(null, () => withUser32(releases.join(\"\\n\"), { timeoutMs: 2_000 }));\n    for (const button of buttons) heldButtons.delete(button);","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/win32.mjs#L181-L217","documentation":"psJson runs a script through psOk (which guarantees a zero exit code) and then parses stdout as JSON via tryJson. If the trimmed stdout is not valid JSON, it throws this ExecError including up to 300 chars of stderr or stdout to show what actually came back. This catches scripts that succeeded but printed unexpected output.","triggerScenarios":"A psJson-backed script prints progress/warning lines before the JSON, emits nothing on stdout, uses ConvertTo-Json without -Compress in a way that mangles output, or writes diagnostics to stdout while stderr is empty.","commonSituations":"Profile scripts ($PROFILE) or modules echoing banners on load; ConvertTo-Json emitting multiple documents for arrays; BOM or console encoding (e.g. UTF-16) corrupting the first bytes; Windows PowerShell 5.1 vs PowerShell 7 differences in JSON formatting.","solutions":["Inspect the 300-char excerpt in the error to see what polluted stdout","In your script, redirect all non-JSON output to stderr (Write-Host/Write-Warning to stderr) or suppress profile loading (-NoProfile)","Ensure a single ConvertTo-Json -Compress -Depth N call is the only stdout output and use Out-String where needed","Force UTF-8 output encoding in the script: [Console]::OutputEncoding = [Text.Encoding]::UTF8"],"exampleFix":"// before\n# powershell\n\"loading...\"\nConvertTo-Json $result\n// after\n# powershell\nWrite-Warning \"loading...\"   # goes to stderr\nConvertTo-Json $result -Compress -Depth 6","handlingStrategy":"validation","validationCode":null,"typeGuard":"function isJsonObject(s) { try { const v = JSON.parse(s); return v && typeof v === 'object'; } catch { return false; } }","tryCatchPattern":"try { return await psJson(script); }\ncatch (e) {\n  if (/did not return JSON/.test(e.message)) log.error('stdout polluted:', e.message);\n  throw e;\n}","preventionTips":["Make ConvertTo-Json -Compress the only stdout output in the script","Route diagnostics through Write-Warning/Write-Host (stderr) and run with -NoProfile","Force UTF-8 output encoding to avoid BOM/encoding corruption","Test scripts across Windows PowerShell 5.1 and PowerShell 7 before shipping"],"tags":["powershell","json","parse-error","windows","stdout"],"backgroundTag":"json-parse-error","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"}