Skip to content

Cloud WebDriver session creation runs under the generic 30s request policy — BrowserStack iOS open fails ~75% of the time and leaks billed provider sessions #1774

Description

@rogerfuentes

Summary

WebDriverClient.createSession() (POST /session) executes under the generic request policy; timeoutMs ?? 30_000, retryAttempts ?? 1 (packages/provider-webdriver/src/webdriver-client.ts:96); and the provider definitions never pass a custom requestPolicy (packages/provider-webdriver/src/provider-definitions.ts), so there is no flag or env var to raise it (open --timeout is rejected with INVALID_ARGS).

BrowserStack App Automate iOS real-device session creation routinely takes 45–90 s. With a 30 s budget × 2 attempts, open aborts client-side at ~60 s on most runs. In our testing (iPhone 17 / iOS 26 and iPhone 16 / iOS 18 pools), open failed 3 of 4 attempts with Error (UNKNOWN): The operation was aborted due to timeout; the single success completed in 59.985 s, inside the window by 15 ms.

The compounding defect: leaked billed sessions

Each timed-out POST /session still completes server-side. Because the client aborted the fetch, it never learns the sessionId and never deletes it; and the automatic retry (retryAttempts: 1 on a non-idempotent request) creates a second one. Net effect: every failed open leaves 2 orphaned running sessions on BrowserStack, billing device minutes until BrowserStack's own idle timeout (~90 s) reaps them. Across a short debugging session we accumulated 6+ leaked sessions. They can only be stopped via the WebDriver hub (DELETE /wd/hub/session/<id>) since BrowserStack's REST API refuses to delete running sessions.

Repro

export BROWSERSTACK_USERNAME=... BROWSERSTACK_ACCESS_KEY=...
agent-device connect browserstack \
  --platform ios --device "iPhone 17" --provider-os-version 26 \
  --provider-app bs://<uploaded-ipa>
agent-device open com.example.app --relaunch
# → ~75% of runs: Error (UNKNOWN): The operation was aborted due to timeout (after ~60s)
# BrowserStack dashboard: 2 new sessions in status "running" per failed open

Diagnostics show the failing phase is lease_allocate (request_failed: "The operation was aborted due to timeout").

Environment

  • agent-device 0.20.8 (also relevant to v0.20.7)
  • Node v22.22.2, macOS (darwin 25.2.0)
  • BrowserStack App Automate, iOS real devices (iPhone 17/26.x, iPhone 16/18.x)
  • App: ~130 MB IPA, pre-uploaded via REST (bs:// ref), so upload time is NOT part of the failing window; this is pure session-creation latency

Suggested fixes

  1. Give createSession its own budget for cloud providers (120–180 s default), or plumb requestPolicy through the provider definitions and expose a flag/env override.
  2. Set retryAttempts: 0 for POST /session; retrying a non-idempotent create doubles the leak and can't succeed inside the same overall deadline anyway.
  3. On client-side abort of a create, attempt cleanup: query the provider REST API for sessions created under this build/label and delete strays, or at minimum surface a warning that a billed session may have been left running.

Workaround we're using

Patching the installed dist: timeoutMs:e.requestPolicy?.timeoutMs??3e4??18e4 in dist/src/src3.js, then restarting the daemon. With 180 s, open succeeds reliably (26–38 s observed). We also sweep status=running sessions via the WebDriver hub after any client-side failure.

Happy to provide diagnostic NDJSON logs / session IDs privately if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions