{"record":{"id":"2a19456fa989b58c","repo":"Hmbown/CodeWhale","slug":"element-does-not-belong-to-the-bound-application-open","errorCode":null,"errorMessage":"element does not belong to the bound application — open_application and observe again","messagePattern":"element does not belong to the bound application — open_application and observe again","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/darwin.mjs","lineNumber":310,"sourceCode":"      throw error;\n    }\n    const result = tryJson(r.stdout, null);\n    const interference = leaseVerdict(result);\n    if (interference !== null) result.user_input_during_lease = interference;\n    if (state.previewEnabled && state.inputApp && [\"type\", \"key_event\", \"pointer_sequence\", \"bg_pointer\", \"bg_key\", \"set_value\", \"select_text\", \"perform_action\", \"hit_test\", \"click_element\", \"scroll_element\", \"focus_element\"].includes(tool)) {\n      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 });","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/darwin.mjs#L292-L328","documentation":"The backend binds input to one application (state.inputApp) established via open_application. assertBoundElement validates that the accessibility element you are targeting was observed from that same application (matching pid). If no app is bound or the element's app_ref.pid differs from the bound pid, it throws so a stale/foreign element is never driven.","triggerScenarios":"Calling an element-targeting input tool (e.g. a11y click/type) with a target whose app_ref.pid is absent or differs from state.inputApp.pid — typically after re-binding with open_application to another app, after the bound app restarted (new pid), or when passing an element from a previous observe() session.","commonSituations":"Automation scripts that observe app A, then open app B, then replay old element handles; app relaunch by an updater changing the pid; caching observe() results across turns; mixing targets from screenshots taken before open_application was called.","solutions":["Call open_application to (re)bind the intended application, then observe() again to get fresh element handles for it.","Re-run observe() after any app relaunch or rebinding — old element references are stale once the pid changes.","Check the element's app_ref.pid matches the currently bound pid before passing it to an input tool.","In multi-app workflows, rebind explicitly each time you switch applications instead of reusing cached targets."],"exampleFix":"// before\nconst el = oldTargets[\"Submit\"]; // observed before rebinding\nawait click({ element: el }); // element does not belong to the bound application\n\n// after\nawait open_application(\"com.example.app\");\nconst fresh = await observe();\nawait click({ element: fresh[\"Submit\"] });","handlingStrategy":"validation","validationCode":"function isUsableTarget(el, boundPid) {\n  return el?.app_ref?.pid === boundPid;\n}\n// before acting:\n// if (!isUsableTarget(el, state.boundPid)) await open_application(app);","typeGuard":null,"tryCatchPattern":"try {\n  await click({ element: el });\n} catch (e) {\n  if (String(e.message).includes('does not belong to the bound application')) {\n    await open_application(el.app_ref);\n    const fresh = await observe();\n    await click({ element: fresh[el.label] });\n  } else throw e;\n}","preventionTips":["Always observe() again after open_application; never reuse element handles across rebinds.","Re-observe after any app relaunch (pid changes invalidate all handles).","Track the bound pid in your automation script and compare it to each target's app_ref.pid.","Scope element caches to a single open_application session."],"tags":["macos","stale-element","accessibility","state"],"backgroundTag":"invalid-state-transition","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"}