skip to content

In Appium, which unit does appium:newCommandTimeout use, and which do the startup timeouts use?

level: juniorimportance: nice to knowfreq 42%

answer

  1. one capability counts differently from the rest
  2. off by a thousand still parses
  3. startup ceilings look like five-digit numbers
  4. one of them is seconds, the rest are not

basics

~20 s

newCommandTimeout is the one Appium timeout counted in seconds. The agent startup capabilities are counted in milliseconds: uiautomator2ServerLaunchTimeout and adbExecTimeout on Android, wdaLaunchTimeout on iOS. Mixing the two units is an error of a thousand.

solid answer

~40 s

`appium:newCommandTimeout` is the odd one out: it is expressed in **seconds**, and it bounds how long the server will wait between commands before it deletes an idle session. Every capability that bounds the agent's startup is expressed in **milliseconds** — on Android `appium:uiautomator2ServerLaunchTimeout` (waiting for `io.appium.uiautomator2.server` to come up) and `appium:adbExecTimeout` (the ceiling on each individual `adb` call), and on iOS `appium:wdaLaunchTimeout` (waiting for WebDriverAgent to be built, installed, launched and answering). So `newCommandTimeout: 60` is a minute, while `wdaLaunchTimeout: 60` is a sixtieth of a second and fails every session at once. The practical tell is magnitude: a startup ceiling written as two digits is almost always a units bug, and a `newCommandTimeout` written as `120000` is a reaper that will never fire.

go deeper

for a junior

Be ready to say which Appium timeout capability is counted in seconds and which in milliseconds, and to name the Android and the iOS startup ones separately. Getting the unit right is the whole of this question.

for a middle

Explain what each timer guards: the idle reaper measures silence between commands the server receives, while the startup ceilings guard installing and launching the on-device agent. Say why the Android and iOS ceilings cover different work.

for a senior

Show how a units mistake presents in production. A five-digit newCommandTimeout leaves stale agents on devices after a client crash, and a two-digit startup ceiling fails every session before the agent can possibly answer.

for a principal

Own the convention. Decide whether capability sets are hand-written or generated from a typed configuration, so a unit is validated once rather than rediscovered by every lane that copies a capability block.

## Why this trips people at all Appium's capability set mixes two different time units, and nothing in the protocol warns you when you pick the wrong one. A session request is just a JSON body: the server reads `appium:newCommandTimeout` as a count of **seconds** and reads every agent-startup capability as a count of **milliseconds**. A number that is wrong by a factor of a thousand is still a perfectly valid number, so the failure never says *bad unit*. It says the session died, or the session never started. ## The seconds clock: the idle reaper `appium:newCommandTimeout` is one of Appium's base capabilities and it is counted in **seconds**. It arms a timer on the server: every time the server finishes answering a command for that session it restarts the timer, and if the timer runs out before the next command arrives the server tears the session down along the same path `DELETE /session/:sessionId` takes. It measures the gap between HTTP requests the server receives — not whether your test process is alive, and not whether the device is busy. Its default is 60, meaning sixty seconds. That is why the value looks so small next to everything else in the same capability object, and it is exactly where the confusion starts: - `"appium:newCommandTimeout": 60` is one minute of allowed silence. - `"appium:newCommandTimeout": 600` is ten minutes. - `"appium:newCommandTimeout": 60000` is not "sixty seconds expressed in milliseconds" — it is roughly sixteen and a half **hours**, which is an idle reaper that will never fire on any run you care about. ## The milliseconds clocks: getting the agent up Everything that bounds the on-device agent's arrival is in **milliseconds**, and the two platforms do not even bound the same work, because the agent is not the same program. | | Android (UiAutomator2 driver) | iOS (XCUITest driver) | |---|---|---| | what has to happen | install and start `io.appium.uiautomator2.server`, with `io.appium.settings` alongside it | build, sign, install and launch **WebDriverAgent**, normally through `xcodebuild` | | the launch ceiling | `appium:uiautomator2ServerLaunchTimeout` | `appium:wdaLaunchTimeout` | | a per-step ceiling | `appium:adbExecTimeout` — the ceiling on **each individual `adb` call**, not on startup as a whole | nothing of this shape; the build is the long pole | | unit | milliseconds | milliseconds | A plausible Android pair therefore reads `"appium:uiautomator2ServerLaunchTimeout": 90000` with `"appium:adbExecTimeout": 40000`, and a plausible iOS one reads `"appium:wdaLaunchTimeout": 240000`. Written as `90`, `40` and `240`, those same capabilities become sub-second ceilings that cannot possibly be met, and every session fails at start. ## Reading a capability set for a units bug 1. Find `appium:newCommandTimeout`. If it is five or six digits, somebody converted it to milliseconds and switched the idle reaper off by accident. 2. Find every other capability whose name ends in `Timeout`. If any of them is one or two digits, it was written in seconds and will expire long before the work it guards can finish. 3. Sanity-check by magnitude rather than by name. Startup ceilings on real hardware are tens of thousands of milliseconds; the idle ceiling is tens or a few hundreds of seconds. ## What each mistake looks like when it fires - **`newCommandTimeout` written in milliseconds** — nothing fails, and that is the problem. The session is simply never reclaimed, so a crashed client leaves the helper server running on the Android device or WebDriverAgent running on the iPhone, and the next run inherits a machine that is not as clean as it assumes. - **`newCommandTimeout` written far too small** — a bakery pre-order test that waits on a slow order-confirmation call comes back to a session the server has already deleted, and the next command fails with an invalid-session error that never mentions a timeout. - **`appium:uiautomator2ServerLaunchTimeout` written in seconds** — the Android session dies during startup while the helper server is still being installed and started. - **`appium:wdaLaunchTimeout` written in seconds** — the iOS session dies almost immediately, long before `xcodebuild` could have produced an agent, and the log shows only that the agent never answered. - **`appium:adbExecTimeout` written in seconds** — Android sessions fail unpredictably, because that ceiling applies per `adb` invocation and every ordinary call now has a budget of a few milliseconds. ## The one-line rule Appium counts the wait for **you** in seconds and the wait for the **device** in milliseconds. `appium:newCommandTimeout` is the member of the first group you meet in ordinary use; `appium:uiautomator2ServerLaunchTimeout`, `appium:adbExecTimeout` and `appium:wdaLaunchTimeout` are all in the second — and naming the platform matters, because Android's two and iOS's one guard entirely different work.

  • If appium:newCommandTimeout is expressed in seconds, what does a value of 0 mean?
    Zero disables the idle timer entirely. The server stops reaping the session for silence and holds it until the client sends `DELETE /session/:sessionId` or the server itself stops. If the client dies first, that keeps the UiAutomator2 helper server alive on Android, or WebDriverAgent alive on iOS, indefinitely.
  • Which Android startup ceiling is per-operation rather than per-session, and why does that matter?
    `appium:adbExecTimeout` bounds each individual `adb` invocation the driver makes, not the whole startup. On a loaded host every small `adb` call gets that same short budget, so a session can fail on an ordinary command long after startup succeeded. iOS has no equivalent, because the XCUITest driver drives `xcodebuild`, `simctl` and `devicectl` rather than `adb`.

saying these in an interview costs you the question

  • Assuming every Appium timeout capability is expressed in milliseconds
  • Setting newCommandTimeout to 60000 and calling it sixty seconds
  • Thinking adbExecTimeout bounds the whole Android session startup rather than each adb call
  • Believing wdaLaunchTimeout has any effect on an Android session
  • Treating uiautomator2ServerLaunchTimeout as an iOS capability as well