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

  1. Take a screenshot on that computer first — it binds the raster that pixel targets are mapped through.
  2. Use target.space === "screen" with screen-point coordinates if you don't need pixel addressing.
  3. Confirm the computer id matches the one you screenshotted (the raster is keyed per computer).
  4. 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

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


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)