microsoft/playwright · error · Error
Connecting to Android devices is not allowed.
Error message
Connecting to Android devices is not allowed.
What it means
Thrown by AndroidDispatcher.devices() when _denyLaunch is true. The Playwright server sets denyLaunch in pre-launched / connect / launch-server modes (playwrightServer.ts, playwrightWebSocketServer.ts, playwrightPipeServer.ts): once the server has pinned or pre-launched a single Android device for the connection, enumerating further devices is forbidden to keep the session isolated.
Source
Thrown at packages/playwright-core/src/server/dispatchers/androidDispatcher.ts:38
import { AndroidDevice } from '../android/android';
import { SdkObject } from '../instrumentation';
import type { RootDispatcher } from './dispatcher';
import type { Android, SocketBackend } from '../android/android';
import type * as channels from '../channels';
import type { Progress } from '../progress';
export class AndroidDispatcher extends Dispatcher<Android, channels.AndroidChannel, RootDispatcher> implements channels.AndroidChannel {
_type_Android = true;
private readonly _denyLaunch: boolean;
constructor(scope: RootDispatcher, android: Android, denyLaunch: boolean) {
super(scope, android, 'Android', {});
this._denyLaunch = denyLaunch;
}
async devices(params: channels.AndroidDevicesParams, progress: Progress): Promise<channels.AndroidDevicesResult> {
if (this._denyLaunch)
throw new Error(`Connecting to Android devices is not allowed.`);
const devices = await this._object.devices(progress, params);
return {
devices: devices.map(d => AndroidDeviceDispatcher.from(this, d))
};
}
}
export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.AndroidDeviceChannel, AndroidDispatcher> implements channels.AndroidDeviceChannel {
_type_AndroidDevice = true;
static from(scope: AndroidDispatcher, device: AndroidDevice): AndroidDeviceDispatcher {
const result = scope.connection.existingDispatcher<AndroidDeviceDispatcher>(device);
return result || new AndroidDeviceDispatcher(scope, device);
}
constructor(scope: AndroidDispatcher, device: AndroidDevice) {
super(scope, device, 'AndroidDevice', {
model: device.model,View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Do not call devices() on a denyLaunch server; use the preLaunchedAndroidDevice already provided in the init result (the device the server pinned for you).
- If you truly need to enumerate devices, start the server in a mode without denyLaunch (plain local android.launchServer / direct driver) instead of preLaunchedAndroidDevice mode.
- Inspect the connection's init result (preLaunchedAndroidDevice / denyLaunch flag) once at startup and branch your code accordingly.
Example fix
// before: always enumerate
const [device] = await playwright._android.devices();
// after: use the server-provided device when present
const device = initResult.preLaunchedAndroidDevice ?? (await playwright._android.devices())[0];
if (!device) throw new Error('no device available'); Defensive patterns
Strategy: validation
Validate before calling
// Check the connection's init result before calling devices().
const init = await playwright.initialize();
if (init.denyLaunch || init.preLaunchedAndroidDevice) {
// Use init.preLaunchedAndroidDevice instead of devices().
} else {
const [device] = await playwright._android.devices();
} Type guard
function hasPreLaunchedAndroidDevice(init: any): init is { preLaunchedAndroidDevice: AndroidDevice } {
return !!init?.preLaunchedAndroidDevice;
} Try / catch
try {
await playwright._android.devices();
} catch (e) {
if (/Android devices is not allowed/.test(e.message)) {
// server denied enumeration; fall back to the preLaunchedAndroidDevice
} else throw e;
} Prevention
- Inspect the init result (denyLaunch / preLaunchedAndroidDevice) once at connection time and cache the decision.
- On managed servers, always use the pinned device rather than enumerating.
- Document whether your server endpoint runs in preLaunchedAndroidDevice mode so clients know not to call devices().
When it happens
Trigger: Calling playwright._android.devices() (or the Android.devices RPC) over a connection whose PlaywrightInitializeResult carried denyLaunch=true. This includes preLaunchedAndroidDevice mode (_initPreLaunchedAndroidMode) and any server started with a constrained launch policy. The check happens before any adb work, so it fires on every devices() call in such sessions.
Common situations: Connecting to a remote Playwright server that was started with a pre-paired Android device (e.g. for a managed device farm or CI grid) and then calling devices() as if it were a local session; using a launchServer-style endpoint for Android automation; misconfigured MCP/remote session that assumes open device enumeration.
Related errors
- Launching more browsers is not allowed.
- Launching more browsers is not allowed.
- No devices found
- No device with serial number '${options.deviceSerialNumber}'
- More than one device found. Please specify deviceSerialNumbe
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/ba8fd513c69f2cd3.
Report an issue: GitHub.