{"record":{"id":"fa4b110769c9a4ad","repo":"can1357/oh-my-pi","slug":"drag-target-must-be-a-selector-string-or-x-numb","errorCode":null,"errorMessage":"Drag target must be a selector string or { x: number, y: number } point","messagePattern":"Drag target must be a selector string or (.+?) point","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/cmux/cmux-tab.ts","lineNumber":1037,"sourceCode":"\t\tconst object = value as Record<string, unknown>;\n\t\treturn {\n\t\t\tx: numberFrom(object.x, 0),\n\t\t\ty: numberFrom(object.y, 0),\n\t\t\twidth: numberFrom(object.width, 0),\n\t\t\theight: numberFrom(object.height, 0),\n\t\t};\n\t}\n\n\tasync #dragPoint(target: DragTarget): Promise<{ x: number; y: number }> {\n\t\tif (typeof target === \"string\") {\n\t\t\tconst box = await this.#selectorBox(this.#selectorSpec(target));\n\t\t\tif (!box) throw new ToolError(`Drag selector did not resolve to a visible element: ${target}`);\n\t\t\treturn { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n\t\t}\n\t\tif (Number.isFinite(target.x) && Number.isFinite(target.y)) {\n\t\t\treturn { x: target.x, y: target.y };\n\t\t}\n\t\tthrow new ToolError(\"Drag target must be a selector string or { x: number, y: number } point\");\n\t}\n\n\tasync #installResponseObserver(): Promise<void> {\n\t\tawait this.#evalScript<boolean>(RESPONSE_OBSERVER_SCRIPT);\n\t}\n\n\tasync #responseCursor(): Promise<number> {\n\t\tconst value = await this.#evalScript<unknown>(\n\t\t\t\"(() => Math.max(0, ((globalThis.__ompCmuxResponses && globalThis.__ompCmuxResponses.nextId) || 1) - 1))()\",\n\t\t);\n\t\treturn numberFrom(value, 0);\n\t}\n\n\tasync #responseRecordsAfter(id: number): Promise<CmuxResponseRecord[]> {\n\t\tconst value = await this.#evalScript<unknown>(\n\t\t\t`(() => ((globalThis.__ompCmuxResponses && globalThis.__ompCmuxResponses.records) || []).filter(record => record.id > ${JSON.stringify(id)}))()`,\n\t\t);\n\t\tif (!Array.isArray(value)) return [];","sourceCodeStart":1019,"sourceCodeEnd":1055,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/cmux/cmux-tab.ts#L1019-L1055","documentation":"`#dragPoint` accepts either a selector string or a `{ x, y }` point. If the target is neither (missing/non-finite x or y), it throws this ToolError. It is an argument-shape guard before any geometry lookup.","triggerScenarios":"Passing an object with missing, null, NaN, or string-typed x/y (e.g. {x: '100', y: 200}); passing undefined/null; passing some other object shape the API doesn't recognize.","commonSituations":"Coordinates coming from an external config or JSON where numbers were parsed as strings; a variable accidentally undefined; mixing up the drag API signature (selectors vs points).","solutions":["Ensure the point target has finite numeric x and y: coerce with Number() and validate Number.isFinite before calling.","Pass a selector string instead of a point if you have an element, not coordinates.","Fix the call site so the right overload is used — don't pass an empty or partial object."],"exampleFix":"// before\ntab.drag('.item', { x: opts.left, y: opts.top }); // opts.left may be undefined/'100'\n// after\nconst x = Number(opts.left), y = Number(opts.top);\nif (Number.isFinite(x) && Number.isFinite(y)) tab.drag('.item', { x, y });\nelse tab.drag('.item', '.dropzone');","handlingStrategy":"validation","validationCode":"function assertDragPoint(t: unknown): asserts t is string | { x: number; y: number } {\n  if (typeof t === 'string') return;\n  const p = t as { x?: unknown; y?: unknown };\n  if (!p || !Number.isFinite(Number(p.x)) || !Number.isFinite(Number(p.y)))\n    throw new TypeError(`drag target must be a selector or {x,y} point, got ${JSON.stringify(t)}`);\n}","typeGuard":"function isDragPoint(t: unknown): t is { x: number; y: number } {\n  return typeof t === 'object' && t !== null && Number.isFinite((t as { x: unknown }).x as number) && Number.isFinite((t as { y: unknown }).y as number);\n}","tryCatchPattern":null,"preventionTips":["Type drag-target parameters as `string | { x: number; y: number }` so bad shapes fail at compile time.","Coerce and Number.isFinite-check coordinates coming from configs/JSON.","Never pass undefined/empty objects as targets."],"tags":["invalid-argument","drag-and-drop","type-error"],"backgroundTag":"invalid-argument-shape","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}