Hmbown/CodeWhale · error · ServerError
no_raster
no_raster
Error message
no screenshot bound on this computer yet — call screenshot first so pixel targets have a frame
What it means
rasterToPoints converts raster-pixel coordinates to screen points using a per-computer bound raster (the last screenshot's pixel size, scale factor, and origin). When no screenshot has been taken on that computer there is no frame to map pixels against, so the server throws code "no_raster" rather than assuming a 1:1 mapping that would click in the wrong place.
Solutions
- Take a screenshot on that computer first — it binds the raster that pixel targets are mapped through.
- Use target.space === "screen" with screen-point coordinates if you don't need pixel addressing.
- Confirm the computer id matches the one you screenshotted (the raster is keyed per computer).
- After a server restart, re-screenshot before any raster-targeted action.
Example fix
// before
await click({ computerId, target: { type: "coordinate", x: 500, y: 300 } }); // raster by default, no frame
// after
await screenshot(computerId); // binds the raster
await click({ computerId, target: { type: "coordinate", space: "raster", x: 500, y: 300 } }); Defensive patterns
Strategy: fallback
Validate before calling
if (target.space !== "screen" && !hasBoundRaster(computerId)) await screenshot(computerId);
Type guard
const canUseRaster = (computerId) => lastRasters.has(computerId);
Try / catch
try {
return await click({ computerId, target: { type: "coordinate", space: "raster", x, y } });
} catch (e) {
if (e.code === "no_raster") {
await screenshot(computerId);
return await click({ computerId, target: { type: "coordinate", space: "raster", x, y } });
}
throw e;
} Prevention
- Screenshot each computer before sending any raster-space coordinates.
- Prefer screen-space targets when your coordinates don't derive from a screenshot.
- Re-screenshot after restarts or when switching between computers.
- Track raster binding per computer id in your automation state.
When it happens
Trigger: A coordinate target with target.space === "raster" (or unset, which defaults to raster space in normalizeTarget) sent to a computer where lastRasters has no entry — no screenshot call has happened in this session, or the raster binding was lost via restart/reset.
Common situations: Replaying a recorded raster-coordinate script against a fresh server or new computer; an agent switches computers and forgets to re-screenshot on the new one; assuming raster space works without a screenshot because screen-space coordinates do.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- target_outside_raster
- bad_target
- A managed, project or plugin connector already uses this…
- Absolute path should not warn
- active plugin registry is missing its pre-dotenv…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/cdccf7710e367cc9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/mcp/server.mjs:176
function resolveElement(target, computer) {
const stateId = target.state_id ?? latestStateByComputer.get(computer.id);
const st = stateId ? appStates.get(stateId) : null;
if (!st) throw new ServerError("unknown_state", target.state_id
? `state_id "${target.state_id}" is unknown or expired — call get_app_state again`
: "no observation on this computer yet — call get_app_state first");
const el = st.elements[target.index];
if (!el) throw new ServerError("unknown_element", `element index ${target.index} is outside state ${stateId} (0..${st.elements.length - 1})`);
return { state: st, element: el, stateId };
}
class ServerError extends Error {
constructor(code, message, extra = null) { super(message); this.code = code; if (extra) this.extra = extra; }
}
/** Map raster-pixel coordinates to screen points using the bound raster. */
function rasterToPoints(computerId, x, y) {
const r = lastRasters.get(computerId);
if (!r) throw new ServerError("no_raster", "no screenshot bound on this computer yet — call screenshot first so pixel targets have a frame");
if (r.pixels?.w != null && r.pixels?.h != null && (x < 0 || y < 0 || x >= r.pixels.w || y >= r.pixels.h)) {
throw new ServerError("target_outside_raster", `target (${x},${y}) is outside the bound raster (${r.pixels.w}x${r.pixels.h} pixels) — take a fresh screenshot`);
}
const scale = r.scale && r.scale > 0 ? r.scale : 1;
return { x: (r.origin?.x ?? 0) + x / scale, y: (r.origin?.y ?? 0) + y / scale };
}
/**
* Normalize a target into backend form: points for coordinates, resolved
* element for elements. Element targets are revalidated against the live
* backend when a resolver is available: stale elements throw `element_stale`,
* moved-but-identical elements are re-aimed at their fresh center
* (sink.reacquired = true so the receipt can say target_reacquired).
*/
async function normalizeTarget(computer, target, kind, resolve, sink) {
if (target?.type === "coordinate") {
if (target.space === "screen") {
if (!Number.isFinite(target.x) || !Number.isFinite(target.y)) {View on GitHub (pinned to 73e0f67d83)