Android emulator crashes during UI assertions on Bitrise CI (Linux Stack)
Is there an existing issue for this?
- [x] I have searched the existing issues and didn't find mine.
Steps to reproduce
Device: Android Emulator (tested on multiple configurations)
- Pixel profile, x86_64 architecture
- API levels tested: 26, 30, 33, 34
- OS versions: Android 8.0, 11, 13, 14
Reproduction Steps:
-
Set up Bitrise CI workflow on
linux-docker-android-22.04stack withg2.linux.largemachine type -
Create Android emulator using
avd-manager@2step:
- avd-manager@2:
inputs:
- api_level: "33"
- tag: google_apis
- profile: pixel
- abi: x86_64
- Wait for emulator boot:
- wait-for-android-emulator@1: {}
- Install Flutter debug APK:
adb install -r app-debug.apk
- Create minimal Maestro flow (login.yaml):
appId: com.example.app
---
- launchApp
- runScript: sleep30.js # 30-second passive wait (tried this when waitForAnimationToEnd didn't work)
- assertVisible: "Welcome" # Crashes here
- Create sleep30.js file:
const start = Date.now();
while (Date.now() - start < 30000) {}
- Run Maestro test:
maestro test login.yaml
Actual results
Emulator crashes with "device 'emulator-5554' not found" error during assertVisible command:
Running login test...
Running on emulator
> Flow login
Launch app "com.likelabs.favorited"... COMPLETED
Run ../scripts/sleep30.js... COMPLETED
Assert that "join the community." is visible...Exception in thread "pool-5-thread-1" java.io.IOException: Command failed (host:transport:emulator-5554): device 'emulator-5554' not found
at dadb.adbserver.AdbServer.send$dadb(AdbServer.kt:103)
at dadb.adbserver.AdbServerDadb.open(AdbServer.kt:148)
at dadb.forwarding.TcpForwarder.handleForwarding$lambda$1(TcpForwarder.kt:64)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
FAILED
Exception in thread "pool-5-thread-3" java.io.IOException: Command failed (host:transport:emulator-5554): device 'emulator-5554' not found
at dadb.adbserver.AdbServer.send$dadb(AdbServer.kt:103)
at dadb.adbserver.AdbServerDadb.open(AdbServer.kt:148)
at dadb.forwarding.TcpForwarder.handleForwarding$lambda$1(TcpForwarder.kt:64)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
Android driver unreachable
==== Debug output (logs & screenshots) ====
/root/.maestro/tests/2025-10-03_190011
❌ Login test failed
adding: 2025-10-03_190011/ (stored 0%)
adding: 2025-10-03_190011/ai-(login).json (deflated 15%)
adding: 2025-10-03_190011/ai-report-login.html (deflated 61%)
adding: 2025-10-03_190011/commands-(login.yaml).json (deflated 87%)
adding: 2025-10-03_190011/maestro.log (deflated 81%)
Expected results
Assertion completes successfully
About app
- This is a closed source Flutter app
- Cross-platform app (iOS and Android), but issue only occurs on Android
- Flutter version: 3.24.5
- Android minSdk: 21, targetSdk: 34 (tested on emulators with API 26, 30, 33, and 34)
About environment
- Java version: 17
- OS: Linux (Ubuntu 22.04 via linux-docker-android-22.04 stack)
- Processor architecture: amd64
Logs
Logs
``` 19:00:11.114 [ INFO] maestro.cli.report.TestDebugReporter.logSystemInfo: Debug output path: /root/.maestro/tests/2025-10-03_190011 19:00:11.118 [ INFO] MAESTRO.logSystemInfo: ---- System Info ---- 19:00:11.118 [ INFO] MAESTRO.logSystemInfo: Maestro Version: 2.0.3 19:00:11.119 [ INFO] MAESTRO.logSystemInfo: CI: bitrise 19:00:11.120 [ INFO] MAESTRO.logSystemInfo: OS Name: Linux 19:00:11.120 [ INFO] MAESTRO.logSystemInfo: OS Version: 5.15.0-138-generic 19:00:11.120 [ INFO] MAESTRO.logSystemInfo: Architecture: amd64 19:00:11.122 [ INFO] MAESTRO.logSystemInfo: Java Version: 17 19:00:11.133 [ INFO] MAESTRO.logSystemInfo: Xcode Version: null 19:00:11.258 [DEBUG] io.micrometer.common.util.internal.logging.InternalLoggerFactory.newDefaultFactory: Using SLF4J as the default logging framework 19:00:11.329 [ INFO] MAESTRO.logSystemInfo: Flutter Version: 3.24.5 19:00:11.457 [ INFO] MAESTRO.logSystemInfo: Flutter Channel: [user-branch] 19:00:11.457 [ INFO] MAESTRO.logSystemInfo: --------------------- 19:00:12.104 [ INFO] maestro.cli.command.TestCommand.runShardSuite: [shard 1] Selected device emulator-5554 using port 7001 with execution plan ExecutionPlan(flowsToRun=[/bitrise/src/maestro-tests/flutter/auth/login.yaml], sequence=FlowSequence(flows=[], continueOnFailure=true), workspaceConfig=WorkspaceConfig(flows=null, includeTags=null, excludeTags=null, local=null, executionOrder=null, baselineBranch=null, notifications=null, disableRetries=false, platform=PlatformConfiguration(android=AndroidConfiguration(disableAnimations=false), ios=IOSConfiguration(disableAnimations=false, snapshotKeyHonorModalViews=null)), testOutputDir=null)) 19:00:16.262 [ INFO] maestro.cli.runner.TestRunner.runSingle$lambda$0: Running flow login.yaml... 19:00:16.282 [ INFO] maestro.Maestro.cachedDeviceInfo_delegate$lambda$0: Getting device info 19:00:16.551 [ INFO] maestro.Maestro.cachedDeviceInfo_delegate$lambda$0: Got device info: DeviceInfo(platform=ANDROID, widthPixels=1080, heightPixels=1920, widthGrid=1080, heightGrid=1920) 19:00:16.642 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$0: Define variables RUNNING 19:00:16.650 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$11: Define variables metadata CommandMetadata(numberOfRuns=null, evaluatedCommand=MaestroCommand(defineVariablesCommand=DefineVariablesCommand(env={MAESTRO_USERNAME=USERNAME, MAESTRO_PASSWORD=PASSWORD, MAESTRO_DRIVER_STARTUP_TIMEOUT=180000, MAESTRO_FILENAME=login}, label=null, optional=false)), logMessages=[], insight=Insight(message=, level=NONE), aiReasoning=null, labeledCommand=null) 19:00:16.652 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$2: Define variables COMPLETED 19:00:16.652 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$0: Define variables RUNNING 19:00:16.653 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$11: Define variables metadata CommandMetadata(numberOfRuns=null, evaluatedCommand=MaestroCommand(defineVariablesCommand=DefineVariablesCommand(env={USERNAME=USERNAME, PASSWORD=PASSWORD}, label=null, optional=false)), logMessages=[], insight=Insight(message=, level=NONE), aiReasoning=null, labeledCommand=null) 19:00:16.653 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$2: Define variables COMPLETED 19:00:16.653 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$0: Apply configuration RUNNING 19:00:16.654 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$11: Apply configuration metadata CommandMetadata(numberOfRuns=null, evaluatedCommand=MaestroCommand(applyConfigurationCommand=ApplyConfigurationCommand(config=MaestroConfig(appId=com.likelabs.favorited, name=null, tags=[], ext={}, onFlowStart=null, onFlowComplete=null), label=null, optional=false)), logMessages=[], insight=Insight(message=, level=NONE), aiReasoning=null, labeledCommand=null) 19:00:16.654 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$2: Apply configuration COMPLETED 19:00:16.655 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$0: Launch app "com.likelabs.favorited" RUNNING 19:00:16.659 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$11: Launch app "com.likelabs.favorited" metadata CommandMetadata(numberOfRuns=null, evaluatedCommand=MaestroCommand(launchAppCommand=LaunchAppCommand(appId=com.likelabs.favorited, clearState=null, clearKeychain=null, stopApp=null, permissions=null, launchArguments=null, label=null, optional=false)), logMessages=[], insight=Insight(message=, level=NONE), aiReasoning=null, labeledCommand=null) 19:00:24.894 [ INFO] maestro.Maestro.launchApp: Launching app com.likelabs.favorited 19:00:24.895 [ INFO] maestro.Maestro.launchApp: Stopping com.likelabs.favorited app during launch 19:00:25.210 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$2: Launch app "com.likelabs.favorited" COMPLETED 19:00:25.211 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$0: Run ../scripts/sleep30.js RUNNING 19:00:25.214 [ INFO] maestro.cli.runner.MaestroCommandRunner.runCommands$lambda$11: Run ../scripts/sleep30.js metadata CommandMetadata(numberOfRuns=null, evaluatedCommand=MaestroCommand(runScriptCommand=RunScriptCommand(script=// Passive sleep for 30 seconds without querying the UI const start = Date.now(); while (Date.now() - startmaestro-test-artifacts (9).zip
Maestro version
2.0.3
How did you install Maestro?
install script (https://get.maestro.mobile.dev)
Anything else?
No response
This feels pretty machine-specific. Have you been able to establish whether the emulator is actually stopped?
Yes, confirmed the emulator fully crashes/stops. Evidence:
- Error explicitly states device 'emulator-5554' not found
- ADB server throws
IOException: Command failed (host:transport:emulator-5554): device 'emulator-5554'not found - Maestro reports "Android driver unreachable"
The crash is reproducible across different Bitrise builds. Interestingly, the same emulator configuration successfully runs native Android instrumented tests via Gradle's connectedAndroidTest without any crashes, which suggests the issue is specific to how Maestro interacts with the emulator.
Just because Maestro can't communicate with an emulator doesn't mean that the emulator isn't running. Have you been able to do something like adb devices after the test fails?
Confirmed - the emulator is actually stopped. After the test failure, I added diagnostics:
adb devices -l
ps aux | grep emulator
Results:
=== Checking emulator status after failure ===
List of devices attached
=== Checking if emulator process is running ===
root 22567 0.0 0.0 6624 2444 ? S 18:03 0:00 grep emulator
The emulator list is empty and no emulator process is running (only the grep command itself appears). The emulator fully crashes during the assertVisible command.
I wouldn't expect Maestro to exert that level of control over an emulator. Perhaps there are logs you can salvage from the machine? My natural instinct would be OOM, but the machine you're running on has 32GB of RAM, so seems a tad unlilkely!
I had a play on a Linux machine today, and was able to reproduce this. From the logs, I can't tell if this is a recent qemu-kvm or Android Emulator release causing this. I was able to do it by launching the emulator then doing this in the Maestro source (running the e2e tests)
cd e2e
download_apps android
install_apps android
run_tests android
Part way through the tests, the Android emulator disappeared.
Logs gave:
[26185.397818] perf: interrupt took too long (4970 > 4963), lowering kernel.perf_event_max_sample_rate to 40000
[27286.415797] nouveau 0000:01:00.0: qemu-system-x86[31092]: job timeout, channel 32 killed!
[28187.429955] kvm: kvm [131177]: vcpu0, guest rIP: 0xffffffffac803a51 Unhandled WRMSR(0xc2) = 0xffff
[28206.472813] workqueue: acpi_ec_event_processor hogged CPU for >10000us 131 times, consider switching to WQ_UNBOUND
I've included the context, in case those lines are relevant, although given the gap in timestamps, I suspect not.
Flipping my emulator's GPU from Automatic to Manual seems to be much more stable.
I've no idea how you'd do this in CI 😬
So I tried passing the following flags to the avd-manager's start_command_flags:
Option 1: swiftshader_indirect (software rendering)
- start_command_flags: "-gpu swiftshader_indirect"
Option 2: host (use host GPU)
- start_command_flags: "-gpu host"
Option 3: off (disable GPU entirely)
- start_command_flags: "-gpu off
None of these GPU modes are fixing it on Bitrise. Are there other workarounds or this a known incompatibility with your Docker-based Linux environment?
On my Linux environment, it wasn't Maestro related at all. The emulator was terminating even if I left it alone.
Were you able to find a set of emulator options that worked for this configuration?