After a timeout, first ask what may already have happened. An API call can lose its response after the phone accepted the action. Retrying a read is usually a different decision from retrying a tap that submits a form or creates a record.
Mobilebox provides explicit errors, fresh observations and an optional idempotency key for phone creation, but it does not make actions or other lifecycle calls idempotent. Your agent or program must distinguish a failed transport, a rejected request, a partially executed batch and an unverified task outcome.
Recover the phone identity before creating another
If a create response was received and says creating or starting, poll that same phone id. Do not issue another create request merely because the first long poll ended before readiness.
curl --fail-with-body "$MSB/v1/phones/$ID?wait=ready&timeout=50" \
-H "Authorization: Bearer $MOBILESANDBOX_API_KEY"Send an Idempotency-Key header with each create, a fresh unique value per intended phone. If the connection failed before you received any phone id, repeat the same request with the same key: for 24 hours it returns the phone the first request made instead of creating and charging for a second one. Without a key, list your project’s phones and inspect names, creation times and state before retrying; a name is a diagnostic label, not a duplicate guard.
Read per-action results even on HTTP 200
An action batch stops on its first failure and returns results plus the current screen. Earlier actions may have succeeded. Replaying the original batch can therefore repeat work that should happen only once.
const failedAt = result.results.findIndex(item => !item.ok)
if (failedAt !== -1) {
console.error('Stopped at action', failedAt + 1)
console.error(result.results[failedAt].error)
// Inspect result.screen; plan the remaining safe work from current state.
}The snippet illustrates result inspection. It deliberately does not auto-replay a suffix: later actions may depend on a changed screen or on side effects outside Android. For MCP, inspect the returned action result text as well; a successful tool transport is not a blanket task-success signal.
Match recovery to the error
| Situation | Useful next step | Dangerous shortcut |
|---|---|---|
| stale_ref | Observe again and select from the latest screen | Reuse the old ref on a changed layout |
| Element not found | Inspect app, dialog and current screen | Tap an approximate coordinate without context |
| Phone still starting | Poll its existing id | Create another phone |
| Capacity or rate limit | Respect the returned wait/retry guidance | Repeated immediate allocation |
| Network timeout after submit | Read the resulting app/server state | Submit the same form again |
The error reference documents code, next, retryable and retry timing. A retryable service error means another request may become useful; it does not prove replaying a side-effecting operation is harmless.
Bound the loop, not just each request
Give a workflow an overall deadline and a limit on repeated attempts. A chain of individually bounded calls can still run forever if each failure restarts the whole chain. Set the phone’s idle_timeout and max_duration too, then keep intentional park/delete cleanup even when a retry budget expires.
On failure, retain enough context to distinguish “not attempted”, “attempted but response unknown” and “observed complete”. That distinction is especially useful for actions such as sending a message or placing a test order. Check the remote result through an authorized application path before deciding to try again.
Test uncertain outcomes before production use
Use a harmless staging operation with a unique marker. Interrupt the caller, reconnect, observe the current app and reconcile the marker. Verify that your recovery policy does not create duplicates and that cleanup still runs.
The batching guide explains where a known sequence helps and where an observation boundary is safer. The quickstart supplies the first bounded lifecycle loop. Add retries only when you can state what has already happened and how the next attempt remains safe.