apache/cordova-android · error · CordovaError
Could not find an available avd port
Error message
Could not find an available avd port
What it means
emulator.get_available_port() lists started emulators (from adb devices) and scans adb's console port range 5584 down to 5554 in steps of 2 (16 ports, the adb convention emulator-5554..emulator-5584). Throws when every port in the range is already occupied by a running emulator.
Source
Thrown at lib/emulator.js:185
return (await Adb.devices())
.filter(id => id.startsWith('emulator-'));
};
/*
* Gets unused port for android emulator, between 5554 and 5584
* Returns a promise.
*/
module.exports.get_available_port = function () {
const self = this;
return self.list_started().then(function (emulators) {
for (let p = 5584; p >= 5554; p -= 2) {
if (emulators.indexOf('emulator-' + p) === -1) {
events.emit('verbose', 'Found available port: ' + p);
return p;
}
}
throw new CordovaError('Could not find an available avd port');
});
};
/*
* Starts an emulator with the given ID,
* and returns the started ID of that emulator.
* If no boot timeout is given or the value is negative it will wait forever for
* the emulator to boot
*
* Returns a promise.
*/
module.exports.start = function (emulatorId, boot_timeout) {
const self = this;
return Promise.resolve().then(function () {
if (!emulatorId) {
throw new CordovaError('No emulator ID given');
}View on GitHub (pinned to 7c1e190064)
Solutions
- Free ports by stopping unneeded emulators: `adb -s emulator-5554 emu kill`, close emulator windows, or `pkill -f qemu-system`.
- If you genuinely need more than 16 concurrent emulators on one host, split them across separate adb servers (ANDROID_ADB_SERVER_PORT) or machines - the port range is fixed.
- Retry `cordova emulate android` once ports are free.
Example fix
# before $ cordova emulate android Could not find an available avd port # after $ adb devices | grep emulator- # identify stale emulators $ adb -s emulator-5554 emu kill $ cordova emulate android
Defensive patterns
Strategy: retry
Validate before calling
const started = await emulator.list_started(); // e.g. ['emulator-5554', 'emulator-5556']
if (started.filter(a => /^emulator-\d+$/.test(a)).length >= 16) {
throw new Error('All 16 adb emulator ports in use - stop unneeded emulators before starting another');
} Try / catch
try {
await emulator.start(avdId, timeout);
} catch (e) {
if (/Could not find an available avd port/.test(e.message)) {
await execa('adb', ['-s', (await emulator.list_started())[0], 'emu', 'kill']);
return emulator.start(avdId, timeout); // retry once after freeing a port
}
throw e;
} Prevention
- Tear emulators down at the end of every CI job (adb emu kill / pkill qemu-system) instead of leaking them.
- Cap parallel emulator jobs per host at well under 16; shard across hosts or adb servers beyond that.
- Monitor `adb devices` count in long-lived test farms.
When it happens
Trigger: emulator.start() -> get_available_port() when 16 or more emulators are already running (emulator-5554 through emulator-5584 all appear in `adb devices`). Typical of parallel CI farms or long-lived emulator processes that were never killed.
Common situations: CI running many concurrent Android jobs against one adb server; leaked detached emulator processes (the start() flow detaches with .unref()); local machines accumulating emulator instances over days.
Related errors
- Could not find target matching ${inspect(spec)}
- Failed to install apk to target: ${output}
- Failed to find 'ANDROID_HOME' environment variable. Try sett
- No emulator ID given
AI-assisted analysis of apache/cordova-android@7c1e190064 (2026-08-22).
Data as JSON: /api/errors/a0616b026ff22b2a.
Report an issue: GitHub.