expo/expo · error · CommandError
EXPO_ADB_USER
EXPO_ADB_USER
Error message
Invalid ADB user number "${userNumber}" set with environment variable EXPO_ADB_USER. Run "adb shell pm list users" to see valid user numbers. What it means
Thrown by ADBServer.resolveAdbPromise (code EXPO_ADB_USER) when an adb command fails with exit status 255 and its stdout contains 'Bad user number'. This indicates the Android multi-user number configured via the EXPO_ADB_USER environment variable is invalid for the connected device/emulator. The error extracts the offending number from adb's output (or falls back to env.EXPO_ADB_USER) and points the user to list valid users.
Source
Thrown at packages/@expo/cli/src/start/platforms/android/ADBServer.ts:112
stdio: 'pipe',
})
);
event('adb_file_output', { output: results });
return results;
}
/** Formats error info. */
async resolveAdbPromise<T>(promise: T | Promise<T>): Promise<T> {
try {
return await promise;
} catch (error: any) {
// User pressed ctrl+c to cancel the process...
if (error.signal === 'SIGINT') {
throw new AbortCommandError();
}
if (error.status === 255 && error.stdout.includes('Bad user number')) {
const userNumber = error.stdout.match(/Bad user number: (.+)/)?.[1] ?? env.EXPO_ADB_USER;
throw new CommandError(
'EXPO_ADB_USER',
`Invalid ADB user number "${userNumber}" set with environment variable EXPO_ADB_USER. Run "adb shell pm list users" to see valid user numbers.`
);
}
// TODO: Support heap corruption for adb 29 (process exits with code -1073740940) (windows and linux)
let errorMessage = (error.stderr || error.stdout || error.message).trim();
if (errorMessage.startsWith(BEGINNING_OF_ADB_ERROR_MESSAGE)) {
errorMessage = errorMessage.substring(BEGINNING_OF_ADB_ERROR_MESSAGE.length);
}
error.message = errorMessage;
throw error;
}
}
}
View on GitHub (pinned to b09195aac2)
Solutions
- List valid users: `adb shell pm list users` and note a valid user id (usually 0).
- Set EXPO_ADB_USER to a valid id, e.g. `export EXPO_ADB_USER=0`, or unset it to use the default.
- Remove the EXPO_ADB_USER line from your shell profile/.env if you don't need multi-user targeting.
- Reconnect the device and recheck users, since user ids can change after resets.
Example fix
// before: export EXPO_ADB_USER=10 # invalid on this device // after: export EXPO_ADB_USER=0
Defensive patterns
Strategy: validation
Validate before calling
import { env } from '../../utils/env';
import { executeAdbAsync } from './adb';
async function isValidAdbUser(user: string | undefined): Promise<boolean> {
if (!user) return true;
const out = await executeAdbAsync(['shell', 'pm', 'list', 'users']);
return new RegExp(`UserInfo\\{${user}:`).test(out);
}
if (!(await isValidAdbUser(env.EXPO_ADB_USER))) {
throw new Error(`EXPO_ADB_USER=${env.EXPO_ADB_USER} is not a valid user id on this device.`);
} Try / catch
try {
await adbServer.resolveAdbPromise(someAdbCall);
} catch (e: any) {
if (e.code === 'EXPO_ADB_USER') {
// unset EXPO_ADB_USER or set it to 0, then retry
} else throw e;
} Prevention
- Leave EXPO_ADB_USER unset unless you target a specific Android multi-user.
- Verify with `adb shell pm list users` before setting the env var.
- Don't copy EXPO_ADB_USER across devices with different user configurations.
When it happens
Trigger: An adb invocation run through resolveAdbPromise rejects with error.status === 255 and error.stdout includes 'Bad user number', which happens when EXPO_ADB_USER points to a user id that doesn't exist on the device (e.g. using --user 999 on a single-user emulator).
Common situations: EXPO_ADB_USER set globally to a value valid on one device but not another. Copying an env var from a multi-user Android device to a single-user emulator. A stale .env or shell profile with an old user number. A device whose user list changed after a factory reset.
Related errors
- Could not find device with name: ${name}
- EMULATOR_NOT_FOUND
- No Android connected device found, and no emulators could be
- NGROK_ADB
- Failed to take Android screenshot: ${error instanceof Error
AI-assisted analysis of expo/expo@b09195aac2 (2026-08-12).
Data as JSON: /api/errors/3fa49abea9dee4b9.
Report an issue: GitHub.