{"record":{"id":"901a042f47143555","repo":"Hmbown/CodeWhale","slug":"no-agent-pointer-position-mouse-move-or-left-mouse-down","errorCode":null,"errorMessage":"no agent pointer position — mouse_move or left_mouse_down first","messagePattern":"no agent pointer position — mouse_move or left_mouse_down first","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/darwin.mjs","lineNumber":1057,"sourceCode":"      const r = await gesture([{ type: MOUSE_MOVED, x: target.x, y: target.y, button: 0, clickState: 0 }], { restore: false, guard: target });\n      return { action_sent: true, strategy: \"event\", at: { x: target.x, y: target.y }, ...pointerCost(r) };\n    },\n    left_mouse_down: async ({ target } = {}) => {\n      assertInScreen(target?.x, target?.y);\n      requireSharedPointer();\n      if (state.pointerLease) throw new ExecError(\"this session already holds the left pointer button; release it first\");\n      await assertOwnsPoint(target.x, target.y);\n      state.pointerLease = await nativeLease(\"pointer_sequence\", { steps: [\n          { type: MOUSE_MOVED, x: target.x, y: target.y, button: 0, clickState: 0 },\n          { type: MOUSE.left.down, x: target.x, y: target.y, button: 0, clickState: 1 },\n        ], restore: false });\n      state.pointer = { x: target.x, y: target.y };\n      return { action_sent: true, strategy: \"event\", at: state.pointer, ...pointerCost(state.pointerLease.receipt) };\n    },\n    left_mouse_up: async ({ target } = {}) => {\n      if (!state.pointerLease) throw new ExecError(\"no agent pointer button is held by this session\");\n      const loc = target ?? state.pointer;\n      if (!loc) throw new ExecError(\"no agent pointer position — mouse_move or left_mouse_down first\");\n      assertInScreen(loc.x, loc.y);\n      // No ownership guard: the button is already held, and the drag may have\n      // legitimately left the originating window.\n      try { await withSignal(null, () => state.pointerLease.release({ point: loc })); }\n      finally { state.pointerLease = null; }\n      state.pointer = { x: loc.x, y: loc.y };\n      return { action_sent: true, strategy: \"event\", at: state.pointer, pointer_moved: true, pointer_restored: false };\n    },\n    left_click_drag: async ({ from_target: from, to } = {}) => {\n      assertInScreen(from?.x, from?.y); assertInScreen(to?.x, to?.y);\n      const steps = [\n        { type: MOUSE_MOVED, x: from.x, y: from.y, button: 0, clickState: 0 },\n        { type: MOUSE.left.down, x: from.x, y: from.y, button: 0, clickState: 1, delayMs: 60 },\n      ];\n      const n = 12;\n      for (let i = 1; i <= n; i++) {\n        steps.push({ type: MOUSE.left.dragged, x: from.x + ((to.x - from.x) * i) / n, y: from.y + ((to.y - from.y) * i) / n, button: 0, clickState: 1, delayMs: 45 });\n      }","sourceCodeStart":1039,"sourceCodeEnd":1075,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/darwin.mjs#L1039-L1075","documentation":"left_mouse_up needs a location to release at: it uses the explicit target, else falls back to state.pointer (the last agent-positioned point). If neither exists — no mouse_move or left_mouse_down was performed in this session — it throws this error rather than guessing a coordinate.","triggerScenarios":"Calling left_mouse_up with no target argument when the session never ran mouse_move or left_mouse_down, so state.pointer is undefined and there is no location to release the button at.","commonSituations":"A fresh session restores only the lease (or the caller assumes pointer state persists across sessions); an agent skips the positioning step before drag-release; a caller passes a malformed target (missing x/y) and it is ignored.","solutions":["Pass an explicit target location: left_mouse_up({ x, y }) with coordinates inside the screen bounds.","Call mouse_move({ x, y }) first so state.pointer is populated, then left_mouse_up() without arguments.","Re-run left_mouse_down in this session before releasing, which also sets state.pointer."],"exampleFix":"// before: release with no position established in this session\nawait left_mouse_up(); // throws\n\n// after: position first, then release\nawait mouse_move({ x: 300, y: 400 });\nawait left_mouse_up();","handlingStrategy":"validation","validationCode":"function assertMouseUpReady(loc) {\n  const ok = (loc && Number.isFinite(loc.x) && Number.isFinite(loc.y)) || lastKnownPointer != null;\n  if (!ok) throw new Error('mouse_up needs a target or prior mouse_move/left_mouse_down');\n}","typeGuard":"function hasPointerPosition(loc) {\n  return loc != null && Number.isFinite(loc.x) && Number.isFinite(loc.y);\n}","tryCatchPattern":"try {\n  await left_mouse_up();\n} catch (e) {\n  if (String(e.message).includes('no agent pointer position')) {\n    await mouse_move({ x: lastKnownPointer.x, y: lastKnownPointer.y });\n    await left_mouse_up();\n  } else throw e;\n}","preventionTips":["Always run mouse_move (or left_mouse_down) before left_mouse_up so the session has a pointer position.","Pass explicit {x, y} coordinates to left_mouse_up when you know the release point — do not rely on session state.","After recreating the session, re-establish pointer position before any release."],"tags":["pointer","mouse","missing-state","macos"],"backgroundTag":"missing-required-argument","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"}