Errors
Purpose
Document the public error-code contract, show where failures appear in CLI output versus result envelopes, and give concrete recovery steps for the most common host, validation, and runtime failures.
Sources
- Public error-code enum:
apps/node/src/contracts/errors.ts - Result envelope shape:
apps/node/src/contracts/result.ts - Execution validation:
apps/node/src/domain/executions/validateExecution.ts - CLI formatting:
apps/node/src/cli/output.ts
Two Failure Shapes
Clawperator surfaces failures in two main shapes.
1. Top-level CLI error object
This appears when Node fails before it can return an execution envelope, for example during argument parsing, payload validation, device selection, or host checks.
Example:
{
"code": "EXECUTION_VALIDATION_FAILED",
"message": "open_uri requires params.uri",
"details": {
"path": "actions.0.params.uri",
"actionId": "open-1",
"actionType": "open_uri"
}
}
Success condition for recovery:
- you change the command or payload
- rerunning no longer returns a top-level
{ "code": ... }object
2. Result envelope failure
This appears when Node successfully sends the command but the execution still fails at dispatch time or during one of the steps.
Per-step example:
{
"envelope": {
"commandId": "read-1",
"taskId": "read-1",
"status": "failed",
"error": "Step a1 (read_text) failed: NODE_NOT_FOUND",
"stepResults": [
{
"id": "a1",
"actionType": "read_text",
"success": false,
"data": {
"error": "NODE_NOT_FOUND",
"message": "No matching node found"
}
}
]
},
"deviceId": "emulator-5554",
"terminalSource": "clawperator_result",
"isCanonicalTerminal": true
}
Envelope-level example with errorCode:
{
"envelope": {
"commandId": "snapshot-1",
"taskId": "snapshot-1",
"status": "failed",
"stepResults": [],
"error": "Accessibility service is not available",
"errorCode": "SERVICE_UNAVAILABLE",
"hint": "Accessibility service not running. Run 'clawperator doctor --fix --device emulator-5554' to diagnose and repair, or 'clawperator operator setup --apk <path-to-apk> --device emulator-5554' to reinstall."
},
"deviceId": "emulator-5554",
"terminalSource": "clawperator_result",
"isCanonicalTerminal": true
}
Success condition for recovery:
envelope.status == "success"- every
stepResults[i].success == true
Public Error Codes
Only the codes defined in apps/node/src/contracts/errors.ts are part of the public error-code contract documented on this page.
| Code | Derived label | Notes |
|---|---|---|
HOST_DEPENDENCY_MISSING |
Host dependency missing | Host |
ADB_NOT_FOUND |
Adb not found | Setup & Connectivity |
NO_DEVICES |
No devices | - |
MULTIPLE_DEVICES_DEVICE_ID_REQUIRED |
Multiple devices device id required | Recovery: pass --device (alias --device-id) when adb shows multiple targets. |
OPERATOR_NOT_INSTALLED |
Operator not installed | - |
DEVICE_NOT_FOUND |
Device not found | Recovery: the --device serial is not connected (alias --device-id). |
EXECUTION_VALIDATION_FAILED |
Execution validation failed | Execution & State |
EXECUTION_ACTION_UNSUPPORTED |
Execution action unsupported | - |
EXECUTION_CONFLICT_IN_FLIGHT |
Execution conflict in flight | - |
RESULT_ENVELOPE_TIMEOUT |
Result envelope timeout | - |
RESULT_ENVELOPE_MALFORMED |
Result envelope malformed | - |
SNAPSHOT_EXTRACTION_FAILED |
Snapshot extraction failed | - |
MISSING_ARGUMENT |
Missing argument | CLI Usage |
NODE_NOT_FOUND |
Node not found | UI & Nodes |
NODE_NOT_CLICKABLE |
Node not clickable | - |
SECURITY_BLOCK_DETECTED |
Security block detected | - |
CONTAINER_NOT_FOUND |
Container not found | - |
CONTAINER_NOT_SCROLLABLE |
Container not scrollable | - |
GESTURE_FAILED |
Gesture failed | - |
NODE_TOO_OLD |
Node too old | Doctor & Host |
ADB_SERVER_FAILED |
Adb server failed | - |
ADB_NO_USB_PERMISSIONS |
Adb no usb permissions | - |
DEVICE_UNAUTHORIZED |
Device unauthorized | - |
DEVICE_OFFLINE |
Device offline | - |
DEVICE_SHELL_UNAVAILABLE |
Device shell unavailable | - |
OPERATOR_VARIANT_MISMATCH |
Operator variant mismatch | Installed release/debug Operator APK variant does not match --operator-package. |
DEVICE_DEV_OPTIONS_DISABLED |
Device dev options disabled | - |
DEVICE_USB_DEBUGGING_DISABLED |
Device usb debugging disabled | - |
DEVICE_ACCESSIBILITY_NOT_RUNNING |
Device accessibility not running | - |
ANDROID_BUILD_FAILED |
Android build failed | - |
ANDROID_INSTALL_FAILED |
Android install failed | - |
ANDROID_APP_LAUNCH_FAILED |
Android app launch failed | - |
SMOKE_OPEN_SETTINGS_FAILED |
Smoke open settings failed | - |
SCRCPY_NOT_FOUND |
Scrcpy not found | - |
APK_VERSION_UNREADABLE |
Apk version unreadable | - |
APK_VERSION_INVALID |
Apk version invalid | - |
CLI_VERSION_INVALID |
Cli version invalid | - |
VERSION_INCOMPATIBLE |
Version incompatible | - |
LOGCAT_UNAVAILABLE |
Logcat unavailable | - |
ANDROID_SDK_TOOL_MISSING |
Android sdk tool missing | - |
EMULATOR_NOT_FOUND |
Emulator not found | - |
EMULATOR_ALREADY_RUNNING |
Emulator already running | - |
EMULATOR_NOT_RUNNING |
Emulator not running | - |
EMULATOR_UNSUPPORTED |
Emulator unsupported | - |
EMULATOR_CREATE_FAILED |
Emulator create failed | - |
EMULATOR_START_FAILED |
Emulator start failed | - |
EMULATOR_STOP_FAILED |
Emulator stop failed | - |
EMULATOR_DELETE_FAILED |
Emulator delete failed | - |
EMULATOR_BOOT_TIMEOUT |
Emulator boot timeout | - |
ANDROID_SYSTEM_IMAGE_INSTALL_FAILED |
Android system image install failed | - |
ANDROID_AVD_CREATE_FAILED |
Android avd create failed | - |
OPERATOR_APK_NOT_FOUND |
Operator apk not found | Operator install |
OPERATOR_INSTALL_FAILED |
Operator install failed | - |
OPERATOR_GRANT_FAILED |
Operator grant failed | - |
OPERATOR_VERIFY_FAILED |
Operator verify failed | - |
RECORDING_ALREADY_IN_PROGRESS |
Recording already in progress | Recording |
RECORDING_NOT_IN_PROGRESS |
Recording not in progress | - |
RECORDING_SESSION_NOT_FOUND |
Recording session not found | - |
RECORDING_PULL_FAILED |
Recording pull failed | - |
RECORDING_PARSE_FAILED |
Recording parse failed | - |
RECORDING_EXPORT_FAILED |
Recording export failed | - |
RECORDING_COMPARE_FAILED |
Recording compare failed | - |
RECORDING_SCHEMA_VERSION_UNSUPPORTED |
Recording schema version unsupported | - |
BROADCAST_FAILED |
Broadcast failed | ADB broadcast dispatch to the Operator package failed. |
PAYLOAD_TOO_LARGE |
Payload too large | - |
DOCTOR_FAILED |
Doctor failed | - |
Fast Triage
- If the output is a top-level object with
code, treat it as a Node-side failure before or outside the Android result envelope. - If
envelope.status == "failed"andstepResultsis empty, treat it as a dispatch, service, or envelope failure. - If
envelope.status == "failed"and one step hassuccess == false, branch on the first failed step'sdata.error. - Prefer exact codes over string-matching the human-readable
messageorerror.
What To Trust
Use these fields in order:
| Situation | Fields to inspect first |
|---|---|
| Top-level CLI error object | code, then details, then message |
| Envelope-level runtime failure | envelope.errorCode, then envelope.hint, then envelope.error |
| Per-step action failure | stepResults[i].data.error, then stepResults[i].data.message |
Notes:
errorCodeis optional on the envelope. Older APK behavior and some unclassified failures may leave it unset.- envelope
errorCodemay contain Android-emitted values such asSERVICE_UNAVAILABLEthat are not part of Node's publicerrors.tsenum - per-step failures do not use the envelope
errorCode; they usually expose the actionable code instepResults[i].data.error StepResult.datavalues are strings, so treatdata.erroranddata.messageas string fields- Node post-processing can turn some Android-internal failure markers into success results, for example normalizing
UNSUPPORTED_RUNTIME_CLOSEinto a successfulclose_appstep when adb pre-flight already succeeded
Recovery Patterns
| Family | Typical codes | What to do next |
|---|---|---|
| Device targeting | NO_DEVICES, DEVICE_NOT_FOUND, MULTIPLE_DEVICES_DEVICE_ID_REQUIRED |
Run clawperator devices, pick one device, and retry with --device <serial> |
| Operator setup | OPERATOR_NOT_INSTALLED, OPERATOR_VARIANT_MISMATCH, OPERATOR_INSTALL_FAILED, OPERATOR_GRANT_FAILED, OPERATOR_VERIFY_FAILED |
Install or repair the expected Operator APK, then rerun the command |
| Host tooling | ADB_NOT_FOUND, ADB_SERVER_FAILED, HOST_DEPENDENCY_MISSING, ANDROID_SDK_TOOL_MISSING, SCRCPY_NOT_FOUND |
Repair the host environment before retrying |
| Payload or flag validation | MISSING_ARGUMENT, EXECUTION_VALIDATION_FAILED, EXECUTION_ACTION_UNSUPPORTED, PAYLOAD_TOO_LARGE |
Change the command or payload. Do not retry unchanged |
| Dispatch or service availability | RESULT_ENVELOPE_TIMEOUT, RESULT_ENVELOPE_MALFORMED, BROADCAST_FAILED, DEVICE_ACCESSIBILITY_NOT_RUNNING, DEVICE_SHELL_UNAVAILABLE |
Run clawperator doctor --json, repair the reported issue, then retry |
| UI lookup or gesture | NODE_NOT_FOUND, NODE_NOT_CLICKABLE, CONTAINER_NOT_FOUND, CONTAINER_NOT_SCROLLABLE, GESTURE_FAILED, SECURITY_BLOCK_DETECTED |
Refresh state with snapshot, wait for UI readiness, or adjust selectors and scroll strategy |
| Recording state | RECORDING_ALREADY_IN_PROGRESS, RECORDING_NOT_IN_PROGRESS, RECORDING_SESSION_NOT_FOUND, RECORDING_PULL_FAILED, RECORDING_PARSE_FAILED, RECORDING_SCHEMA_VERSION_UNSUPPORTED |
Repair recording state or use the right session before retrying |
Key Cases
EXECUTION_VALIDATION_FAILED
Use this when the command or payload is structurally wrong before Android execution starts.
Common triggers:
- missing required action fields such as
open_uri.params.uri - invalid ranges such as
scroll_until.maxScrolls > 200 - selector parser violations such as mixing
--selectorwith shorthand flags - invalid JSON payloads for
clawperator exec
Typical output:
{
"code": "EXECUTION_VALIDATION_FAILED",
"message": "scroll_until params.maxScrolls must be an integer in [1, 200]",
"details": {
"path": "actions.0.params.maxScrolls",
"actionId": "scroll-1",
"actionType": "scroll_until"
}
}
Recovery:
- fix the payload
- rerun validation
- do not retry unchanged
MISSING_ARGUMENT
Use this for CLI commands that are missing a required positional argument or required flag value.
Common triggers:
execwithout a payloadwait-for-navwithout--timeoutread-valuewithout any label selector flags
Example:
{
"code": "MISSING_ARGUMENT",
"message": "wait-for-nav requires --timeout <ms>."
}
Recovery:
- add the missing argument or flag
- rerun the command
RESULT_ENVELOPE_TIMEOUT
Use this when Node dispatched the command but did not receive a valid [Clawperator-Result] envelope before the execution timeout expired.
Typical fields:
{
"code": "RESULT_ENVELOPE_TIMEOUT",
"message": "Timed out waiting for [Clawperator-Result]",
"details": {
"commandId": "snapshot-1",
"taskId": "snapshot-1",
"lastActionId": "a1",
"lastActionType": "snapshot_ui",
"lastActionCaveat": "payload-last only; Android execution position is unknown",
"elapsedMs": 30000,
"timeoutMs": 30000
},
"hint": "No correlated Android log lines were captured. This often indicates an APK/CLI version mismatch or an accessibility service issue. Run 'clawperator doctor --json --device emulator-5554 --operator-package com.clawperator.operator.dev' to diagnose."
}
Recovery:
- run
clawperator doctor --json - if
hintmentions no correlated Android log lines, treat it as a compatibility or accessibility diagnostic path rather than a generic retry - confirm the accessibility service and operator package are healthy
- increase timeout only if the action legitimately needs more wall-clock time
OPERATOR_NOT_INSTALLED
Use this when the requested operator package is not installed on the selected device.
Typical recovery:
clawperator operator setup --apk <path-to-apk> --device <device_serial> --operator-package <package_name>
If you are doing local branch validation, prefer the debug package:
com.clawperator.operator.dev
OPERATOR_VARIANT_MISMATCH
Use this when the device has an installed Operator APK, but it is the other known package variant than the one requested.
Recovery options:
- pass the installed package via
--operator-package - or reinstall the intended APK variant
NODE_NOT_FOUND
This usually appears as a per-step failure in stepResults[i].data.error, not as the top-level CLI code.
Common triggers:
- the selector never matched
- the app navigated somewhere unexpected
- the UI had not settled before the action ran
- the target was inside a different scroll container
Recovery:
- run
snapshotorread --jsonto inspect current UI state - add
waitorsleepbefore the failing action when appropriate - tighten or loosen the selector based on what the snapshot actually shows
- add a container selector or a scroll step if the target is off-screen
DEVICE_ACCESSIBILITY_NOT_RUNNING
This is a doctor- and readiness-related failure indicating the Operator accessibility service is not active.
Recovery:
- run
clawperator doctor --fix --device <serial> - if needed, reinstall the Operator package and re-enable accessibility access
Legacy CLI Usage Objects
Some CLI handlers and tests still emit usage-style objects with string codes that are not part of apps/node/src/contracts/errors.ts. Treat those as command-line usage failures, not as public stable error codes.
What this means for agents:
- if the code is in
errors.ts, you can branch on it as part of the public contract - if the code is not in
errors.ts, treat it as a CLI-specific usage object and prefer fixing the command shape rather than building long-term logic around that string - similarly, Android may emit envelope
errorCodevalues outside the Node enum; branch on them when present in the envelope, but do not confuse them with the documented Node-side top-levelcodecontract