expo/expo · warning · CommandError
APPLE_DEVICE_LOCKED
APPLE_DEVICE_LOCKED
Error message
Device is currently locked.
What it means
Thrown by LockdownProtocolReader.parseBody (code APPLE_DEVICE_LOCKED) when a lockdown plist response contains Error === 'DeviceLocked'. This is the lockdown-layer signal that the device screen is locked, and it is the primary source of the APPLE_DEVICE_LOCKED code that bubbles up to installOnDeviceAsync's interactive unlock-retry prompt. It is raised before any service-specific logic runs, because most lockdown operations require an unlocked device.
Source
Thrown at packages/@expo/cli/src/run/ios/appleDevice/protocol/LockdownProtocol.ts:72
constructor(socket: Socket) {
super(socket, new ProtocolReaderFactory(LockdownProtocolReader), new LockdownProtocolWriter());
}
}
export class LockdownProtocolReader extends PlistProtocolReader {
constructor(callback: (data: any) => any) {
super(LOCKDOWN_HEADER_SIZE, callback);
}
parseHeader(data: Buffer) {
return data.readUInt32BE(0);
}
parseBody(data: Buffer) {
const resp = super.parseBody(data);
if (isLockdownErrorResponse(resp)) {
if (resp.Error === 'DeviceLocked') {
throw new CommandError('APPLE_DEVICE_LOCKED', 'Device is currently locked.');
}
if (resp.Error === 'InvalidService') {
let errorMessage = `${resp.Error}: ${resp.Service} (request: ${resp.Request})`;
if (resp.Service === 'com.apple.debugserver') {
errorMessage +=
'\nTry reconnecting your device. You can also debug service logs with `export DEBUG=expo:xdl:ios:*`';
}
throw new CommandError('APPLE_DEVICE_LOCKDOWN', errorMessage);
}
throw new CommandError('APPLE_DEVICE_LOCKDOWN', resp.Error);
}
return resp;
}
}
export class LockdownProtocolWriter implements ProtocolWriter {View on GitHub (pinned to b09195aac2)
Solutions
- Unlock the device (enter passcode) and retry — installOnDeviceAsync already prompts for this.
- Disable auto-lock (Settings → Display & Brightness → Auto-Lock → Never) during development.
- Ensure the device is awake by tapping the screen before the operation starts.
- For CI, keep the device unlocked via power/screen policy.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await client.doHandshake(pairRecord);
} catch (err) {
if (err instanceof CommandError && err.code === 'APPLE_DEVICE_LOCKED') {
// surface an 'unlock the device' prompt, then retry
}
throw err;
} Prevention
- Unlock the device before any lockdown operation.
- Disable auto-lock during development.
- Re-enter the passcode after a reboot before running device commands.
When it happens
Trigger: Any lockdown request (GetValue, StartService, StartSession, etc.) issued while the device is locked — lockdown returns a plist with Error='DeviceLocked' and the reader escalates it.
Common situations: Device locked at the moment run:ios / install runs; passcode-required-after-reboot state; device auto-locked during a long build before the install step.
Related errors
- Error starting service ${name}
- Error starting session
- Error getting lockdown value
- No bounds returned in response
- No output path returned in response
AI-assisted analysis of expo/expo@b09195aac2 (2026-08-12).
Data as JSON: /api/errors/0a89cad0d7c936b5.
Report an issue: GitHub.