{"record":{"id":"8a2837f373e02eef","repo":"Hmbown/CodeWhale","slug":"this-executor-cannot-safely-own-held-input-update-computer","errorCode":null,"errorMessage":"This executor cannot safely own held input; update Computer Use","messagePattern":"This executor cannot safely own held input; update Computer Use","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/darwin.mjs","lineNumber":316,"sourceCode":"      try { await updatePreview(); } catch (error) { result.preview_error = error.message; }\n    }\n    return result;\n  }\n\n  async function requireBackgroundActions() {\n    if ((await native(\"input_capabilities\"))?.background_actions !== 1) {\n      throw Object.assign(new ExecError(\"Update the Computer Use helper to use background focus, selection, context menus and scrolling.\"), { code: \"app_upgrade_required\" });\n    }\n  }\n\n  function assertBoundElement(target) {\n    if (!state.inputApp || target.app_ref?.pid !== state.inputApp.pid) throw new ExecError(\"element does not belong to the bound application — open_application and observe again\");\n    if (!Array.isArray(target.path) || !Number.isInteger(target.windowIndex) || !target.role) throw new ExecError(\"element has no resolved accessibility identity\");\n  }\n\n  async function nativeLease(tool, args) {\n    if (tool === \"pointer_sequence\") requireSharedPointer();\n    if (!exec.runInputLease) throw new ExecError(\"This executor cannot safely own held input; update Computer Use\");\n    if ((await native(\"input_capabilities\"))?.input_lease !== 1) throw new ExecError(\"The native helper needs an update for disconnect-safe held input\");\n    const helper = await nativeHelper();\n    try {\n      return await exec.runInputLease(helper, [JSON.stringify({ tool, args: { ...args, ...yieldArgs, input_app_ref: state.inputApp, foreground_input: state.foregroundInput, owner_pipe: true, input_lease: true } })]);\n    } catch (error) {\n      error.code = nativeErrorCode(error.message) ?? error.code;\n      throw error;\n    }\n  }\n\n  async function updatePreview(show = false) {\n    const win = await native(\"window_info\", { app_ref: state.inputApp });\n    const dir = path.join(stateDir(), \"preview\");\n    fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n    const temp = path.join(dir, \"next.png\"), file = path.join(dir, \"latest.png\");\n    const r = await runL(\"screencapture\", [\"-x\", \"-o\", \"-l\", String(win.window_id), \"-t\", \"png\", temp], { timeoutMs: 8000 });\n    if (r.code !== 0) throw new ExecError(`background preview capture failed: ${r.stderr}`);\n    fs.renameSync(temp, file);","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/darwin.mjs#L298-L334","documentation":"Held input (drags, press-and-hold sequences) must be executed by an executor that can safely own a lease — i.e. the host's Computer Use runtime exposes runInputLease so held state is released if the agent disconnects. When the executor object lacks this capability, nativeLease throws instead of leaking stuck pointer state.","triggerScenarios":"Calling a tool that routes through nativeLease (e.g. pointer_sequence, which also triggers requireSharedPointer) on an executor built without runInputLease — an older or minimal Computer Use host/executor implementation.","commonSituations":"Running the darwin backend under an outdated or custom executor that predates the input-lease API; embedding the backend in a harness that wires only runInput; plugin/host version mismatch after a Computer Use update.","solutions":["Update the Computer Use host/executor to a version that implements runInputLease.","If you supply a custom executor, add a runInputLease(helper, argsJson) implementation that can release the lease on disconnect/crash.","As a stopgap, avoid held-input tools (drags / pointer_sequence) and use tap or accessibility actions that don't require a lease.","Verify the wiring: log which executor object the backend was constructed with and confirm exec.runInputLease is a function."],"exampleFix":"// before (custom executor)\nconst exec = { runInput: runInput }; // no runInputLease\n\n// after\nconst exec = { runInput, runInputLease }; // lease-capable executor","handlingStrategy":"try-catch","validationCode":"if (typeof exec?.runInputLease !== 'function') {\n  console.warn('executor lacks input-lease support; held-input tools unavailable');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await pointer_sequence({ actions: drag });\n} catch (e) {\n  if (String(e.message).includes('cannot safely own held input')) {\n    // fall back to non-lease actions\n    await click({ element: target });\n  } else throw e;\n}","preventionTips":["Pin Computer Use host to a version whose executor implements runInputLease.","Feature-detect exec.runInputLease at startup and disable drag/hold tools when absent.","Keep custom executors in sync with the Computer Use executor contract.","Prefer accessibility actions for drags where possible — they need no held-input lease."],"tags":["macos","held-input","executor","version-compatibility"],"backgroundTag":"feature-not-enabled","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}