Hmbown/CodeWhale · error · ServerError
element_no_geometry
element_no_geometry
Error message
element ${target.index} of ${where} has no cached geometry — use a coordinate target What it means
normalizeTarget computes a click point from an element's cached position and size for a11y-center targeting. If neither the fresh nor cached element carries geometry (position/size), the library cannot compute a center and throws element_no_geometry, telling the caller to fall back to an explicit coordinate target.
Solutions
- Use a coordinate target {type:'coordinate',x,y} derived from the screenshot instead of the element target.
- Call get_app_state with detail:'full' to obtain elements that include position and size.
- Re-observe to refresh the raster binding, then retry the element target.
- Pick a different element in the tree that carries bounds.
Example fix
// before
await click({ target: { type: 'element', index: 5 } });
// after
if (el.position && el.size) {
await click({ target: { type: 'element', index: el.index } });
} else {
await click({ target: { type: 'coordinate', x: el.centerX, y: el.centerY } });
} Defensive patterns
Strategy: fallback
Validate before calling
function hasGeometry(el) { return !!(el && el.position && el.size && typeof el.position.x === 'number' && typeof el.size.w === 'number'); } Type guard
function hasGeometry(el) { return !!el?.position && !!el?.size; } Try / catch
try { await click({ target: { type: 'element', index } }); }
catch (e) { if (e?.code === 'element_no_geometry') { await click({ target: { type: 'coordinate', x, y } }); } else throw e; } Prevention
- Request detail:'full' observations when you need element bounds.
- Prefer coordinate targets for elements known to lack bounds.
- Re-observe before acting so fresh geometry is available.
- Filter out boundless container nodes when choosing targets.
When it happens
Trigger: Using an element target for a click-type action where resolveElement returned an element whose cached position/size are missing and the live re-resolution also returned no geometry.
Common situations: Observations taken with detail:'compact' or filtered results that omit geometry; container or text-only AX nodes with no bounds; raster binding expired so fresh geometry is unavailable.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- application not found or name is ambiguous in the AT-SPI…
- AT-SPI action failed
- AT-SPI resolve failed
- AT-SPI walk failed — is python3-pyatspi installed and the…
- Codewhale stream-json omitted terminal metadata
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9f030181711ee4dc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/mcp/server.mjs:240
// In-place replacement: same role and geometry but a different label is
// still a different element (e.g. "Load" → "Confirm").
if (fresh.label !== element.label) {
throw new ServerError("element_stale", `element ${target.index} of ${where} changed label (${element.label} → ${fresh.label}) — call get_app_state again`);
}
}
if (kind === "semantic") {
return {
app_ref: state.app_ref, windowIndex: element.windowIndex ?? 0, path: element.path,
strategy: "a11y", role: element.role, label: element.label, reacquired: false,
...(element.runtime_id ? { runtime_id: element.runtime_id, window_runtime_id: element.window_runtime_id } : {}),
};
}
const moved = !!fresh && (
fresh.position?.x !== element.position?.x || fresh.position?.y !== element.position?.y ||
fresh.size?.w !== element.size?.w || fresh.size?.h !== element.size?.h);
const pos = fresh?.position ?? element.position;
const sz = fresh?.size ?? element.size;
if (!pos || !sz) throw new ServerError("element_no_geometry", `element ${target.index} of ${where} has no cached geometry — use a coordinate target`);
if (moved && sink) sink.reacquired = true;
// Keep the element identity as well as geometry: semantic clicks must not
// substitute whichever element happens to occupy an oversized AX center.
const c = { x: Math.round(pos.x + sz.w / 2), y: Math.round(pos.y + sz.h / 2) };
return { ...c, strategy: "a11y-center", role: element.role, label: element.label, app_ref: state.app_ref,
windowIndex: element.windowIndex ?? 0, path: element.path, reacquired: moved };
}
throw new ServerError("bad_target", "target must be {type:'coordinate',x,y} or {type:'element',index} (state_id optional to pin a specific observation)");
}
function bindRaster(computer, shot) {
lastRasters.set(computer.id, {
file: shot.file ?? shot.path,
scale: shot.scale ?? 1,
origin: shot.points ?? { x: 0, y: 0 },
pixels: shot.pixels ?? null,
capturedAt: shot.capturedAt ?? new Date().toISOString(),
});View on GitHub (pinned to 73e0f67d83)