Hmbown/CodeWhale · error · ServerError

unsupported_on_backend

unsupported_on_backend

Error message

"${name}" is not implemented on the ${computer.platform ?? computer.transport} backend

What it means

The Codewhale Computer Use MCP server resolves each tool call to a platform-specific backend (macOS/Windows/accessibility/remote via computer.transport). If the resolved backend object does not expose the method that implements the requested tool, the server refuses the call with code 'unsupported_on_backend' instead of dispatching it and failing opaquely. It means the tool exists in the catalog but is genuinely not implemented on the backend currently bound to the computer.

Solutions

  1. Check which computer/binding the tool call targets and switch to a computer whose platform/transport implements the tool (call computer_list to see available computers).
  2. Consult the tool catalog to confirm the tool is supported for the current transport (REMOTE_TOOLS allow-list for remote agents); pick a supported equivalent tool.
  3. Update/restart the Computer Use helper app so the backend build matches the plugin (see the stale-version note the server emits) — a missing method often means an old build.
  4. If this is your own backend contribution, implement the missing backend[BACKEND_METHOD[tool]] method for that platform.

Example fix

// before
call({ name: 'set_value', arguments: { computer_id: 'remote-agent-1', target: { type: 'element', index: 4 } } })
// after — use a computer whose platform implements the tool
call({ name: 'set_value', arguments: { computer_id: 'local-mac-1', target: { type: 'element', index: 4 } } })
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the tool is dispatched to a backend that implements it (client-side knowledge)
const remote = computer.transport === 'ssh';
if (remote && !REMOTE_TOOLS.has(toolName)) throw new Error(`${toolName} is not available on remote computers`);

Type guard

function backendSupports(backend, tool, methodMap) { return typeof backend?.[methodMap[tool] ?? tool] === 'function'; }

Try / catch

try {
  const res = await callTool({ name: tool, arguments: args });
} catch (e) {
  if (e?.code === 'unsupported_on_backend') {
    // switch computer or fall back to a supported tool
    const computers = await callTool({ name: 'computer_list', arguments: {} });
    console.error(`${e.message}; available: ${JSON.stringify(computers)}`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling a tool whose BACKEND_METHOD is missing on the active backend — e.g. calling an accessibility-only tool on a computer whose transport is a remote agent, or calling a platform-specific action on a backend stub without that method. computer.platform ?? computer.transport is used to name the backend in the message.

Common situations: 1) Targeting a remote/ssh computer with a tool the remote agent allow-list does not cover. 2) A stub/mock or partial backend used in development or tests lacking that tool's method. 3) Version skew where an older helper app does not yet implement a newly added tool. 4) Wrong computer selected (platform mismatch) in a multi-computer session.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/57d7a54d31a345d0. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/mcp/server.mjs:997

        }
      }
      if (backendMethod === "zoom") bindZoomRaster(computer, zoomParent, args.region, ex.filesLocal ? data?.file ?? data?.path : null);
      if (name === "get_app_state") {
        data = observeState(computer, wireArgs.app_ref, data, args);
      }
      if (backendMethod === "probe") Object.assign(data, { via: ex.kind, app: ex.app ?? null });
      if (backendMethod === "probe" && data?.app?.version && data.app.version !== APP_VERSION) {
        // The helper owns the modules it loaded at start, so a plugin update
        // without a helper restart serves the previous build's behavior. Say
        // so instead of letting the agent debug a build that is not running.
        data.app.bundled_version = APP_VERSION;
        data.app.stale = true;
        data.note = [data.note, `The running helper reports ${data.app.version} but this plugin is ${APP_VERSION} — restart the Codewhale Computer Use app to load the current build.`].filter(Boolean).join(" ");
      }
    } else {
      const backend = await getBackend(computer, binding);
      if (typeof backend[backendMethod] !== "function") {
        throw new ServerError("unsupported_on_backend", `"${name}" is not implemented on the ${computer.platform ?? computer.transport} backend`);
      }
      const resolve = typeof backend.resolve_element === "function" ? (req) => backend.resolve_element(req) : null;
      const prepared = await prepareArgs(computer, name, args, resolve, sink);
      throwIfAborted();
      await assertCurrentRoute(computer, binding);
      if (controlStopped && !READ_ONLY_TOOLS.has(name)) throw new ServerError("control_stopped", "stop_computer_control is active; no further actions are permitted this session");
      inFlight++;
      try {
        dispatched = true;
        data = name === "type"
          ? await invokeType((tool, a) => backend[BACKEND_METHOD[tool] ?? tool](a), prepared)
          : await backend[backendMethod](prepared);
      } finally {
        inFlight--;
      }
      await assertCurrentRoute(computer, binding, true);
      if (Array.isArray(data)) data = { items: data }; // keep receipts objects
      if (name === "screenshot") bindRaster(computer, data);

View on GitHub (pinned to 73e0f67d83)