{"record":{"id":"00dfef3da2241dfb","repo":"Hmbown/CodeWhale","slug":"unknown-recording-id-win32","errorCode":null,"errorMessage":"unknown recording \"${id}\"","messagePattern":"unknown recording \"(.+?)\"","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/win32.mjs","lineNumber":579,"sourceCode":"      return { text: j.text ?? \"\", encoding: \"utf8\" };\n    },\n    write_clipboard: async ({ text }) => {\n      const b64 = Buffer.from(String(text ?? \"\"), \"utf16le\").toString(\"base64\");\n      await psOk(`Set-Clipboard -Value ([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('${b64}')));\nWrite-Output '{\"ok\": true}';`, { timeoutMs: 10_000 });\n      return { written: String(text ?? \"\").length };\n    },\n    cursor_position: async () => {\n      const j = await psJson(`${USER32_PRELUDE}\n$p = New-Object User32+POINT;\n[void][User32]::GetCursorPos([ref]$p);\nWrite-Output ('{\"x\": ' + $p.X + ', \"y\": ' + $p.Y + '}');`);\n      return { x: j.x, y: j.y };\n    },\n    recordingStart: async () => {\n      throw Object.assign(new ExecError(\"Recording is unavailable on this platform until the recorder has session-owned cleanup. Use screenshots instead.\"), { code: \"owned_recording_unavailable\" });\n    },\n    recordingStop: async ({ id }) => { throw new ExecError(`unknown recording \"${id}\"`); },\n    recordingStatus: ({ id }) => ({ id, running: false }),\n    recordingList: async () => {\n      const dir = recordingsDir();\n      const out = fs.existsSync(dir)\n        ? fs.readdirSync(dir).filter((f) => /\\.mp4$/i.test(f)).map((f) => {\n            const st = fs.statSync(path.join(dir, f));\n            return { file: path.join(dir, f), bytes: st.size, modifiedAt: st.mtime.toISOString() };\n          }).sort((a, b) => b.modifiedAt.localeCompare(a.modifiedAt)).slice(0, 50)\n        : [];\n      return { dir, recordings: out, running: [] };\n    },\n  };\n\n  async function clickAt(button, x, y, clicks) {\n    if (!Number.isFinite(Number(x)) || !Number.isFinite(Number(y))) throw new ExecError(\"coordinates must be finite numbers\");\n    const flags = button === 1 ? \"RIGHTDOWN, RIGHTUP\" : button === 2 ? \"MIDDLEDOWN, MIDDLEUP\" : \"LEFTDOWN, LEFTUP\";\n    const seq = [];\n    for (let i = 0; i < clicks; i++) seq.push(`[User32]::mouse_event([User32]::${flags.split(\",\")[0].trim()}, 0, 0, 0, [UIntPtr]::Zero); Start-Sleep -Milliseconds 40; [User32]::mouse_event([User32]::${flags.split(\",\")[1].trim()}, 0, 0, 0, [UIntPtr]::Zero); Start-Sleep -Milliseconds 60;`);","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/win32.mjs#L561-L597","documentation":"recordingStop on win32 always fails because recordingStart on this platform throws (recording is unavailable until the recorder has session-owned cleanup), so no recording handle can ever exist. Stopping a recording with any id therefore throws 'unknown recording' — the id cannot match a live recording. recordingStatus always reports running:false.","triggerScenarios":"Calling recordingStop({ id }) on the win32 backend with any id value — a previously started-looking id, a stale id from another backend, or a fabricated one. Unconditional, since no recording can ever start on this backend.","commonSituations":"Agents replaying a start/stop recording workflow ported from the macOS/Linux backend; cleanup handlers blindly calling recordingStop in a finally block; ids persisted from an earlier session.","solutions":["Do not call recordingStart/recordingStop on win32 — use screenshot actions instead, as the recordingStart error message advises.","Guard cleanup code: only call recordingStop if recordingStart succeeded (track the returned id).","Use recordingStatus({ id }) (it never throws) to check running:false before attempting a stop.","If screen recording is required, run on a platform whose backend supports session-owned recorder cleanup."],"exampleFix":"// before\nconst rec = await backend.recordingStart({});\ntry { /* work */ } finally { await backend.recordingStop({ id: rec.id }); }\n// after\nlet rec = null;\ntry { rec = await backend.recordingStart({}).catch(() => null); } catch {}\ntry { /* work */ } finally { if (rec) await backend.recordingStop({ id: rec.id }); }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"const canRecord = (backend) => backend.backendId !== 'win32';","tryCatchPattern":"try {\n  await backend.recordingStop({ id });\n} catch (e) {\n  if (/unknown recording/.test(e.message)) return { stopped: false, reason: 'recording unsupported on this backend' };\n  throw e;\n}","preventionTips":["Never call recordingStart/recordingStop on win32; use screenshots.","Only stop recordings whose id came from a successful recordingStart in the same session.","Use recordingStatus (non-throwing, always running:false on win32) to probe before stopping.","Guard finally-block cleanup so it skips stop calls when start never succeeded."],"tags":["windows","recording","resource-not-found","unsupported-platform"],"backgroundTag":"record-not-found","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"}