EmuLabZip logo EmuLabZip

Troubleshooting

Last updated · Edit this page on GitHub

My Android emulator does not show up#

  1. Run adb devices. If the emulator is not listed there, EmuLabZip cannot see it either. Restart it, or run adb kill-server && adb start-server.
  2. The device picker footer shows adb unavailable when adb cannot be found. Install the Android SDK platform tools, or point ANDROID_HOME or EMULABZIP_ADB at your SDK.
  3. A device listed as unauthorized is waiting for you to accept the USB debugging prompt.
  4. A custom ADB server port must be set with ANDROID_ADB_SERVER_PORT or ADB_SERVER_SOCKET for EmuLabZip too.

My simulator does not show up#

  • Only booted iOS simulators are listed. Check with xcrun simctl list devices booted.
  • The footer shows simctl unavailable when Xcode's command line tools are missing. Run xcode-select --install, or sudo xcode-select -s /Applications/Xcode.app if several Xcode versions are installed.

The log is empty#

  • On Android, check that adb logcat prints lines.
  • Look at the minimum level and the filters; Reset filters appears when lines exist but none match.
  • The app filter needs the app to be running. Start the app; the filter picks up the new process id automatically.

The log is too busy#

See The unified log is busy. On Android, raise the minimum level or filter by tag.

Screenshots fail#

  • On Android, adb exec-out screencap -p > shot.png must work. Some secure screens (DRM video, banking apps) are black by design.
  • On iOS, xcrun simctl io booted screenshot shot.png must work.

Storage says "only debuggable apps can be browsed"#

Android only lets run-as read the private data of debuggable apps. Install a debug build of your app, or try the tools with the sample app (tools/sample-app/install.sh). Shared storage works for every app.

Heap dumps fail on Android#

am dumpheap needs a debuggable app, or an emulator image of the userdebug/eng type (images without Google Play). The error shows the reason Android gave, for example Process not debuggable.

Performance shows no frame rate#

Frames are only counted while the app draws. Interact with the app; a static screen renders nothing. On the iOS Simulator, frame metrics arrive with Instruments traces in Phase 4.

Network: nothing shows up#

  • Check that the device says sending traffic here. On Android, adb shell settings get global http_proxy should print 127.0.0.1:<port>.
  • Some apps ignore the system proxy (those that open sockets themselves, or use HTTP/3). They cannot be captured.
  • Apps that cache heavily may not ask the network at all. Clear their data or use a fresh URL.

Network: HTTPS requests fail or show as "Connections"#

The device does not trust the certificate, or the app pins its server's. Press Certificate and follow what it says. On Android images from Google Play only Chrome and apps that allow user certificates will trust it; see the certificate. A banner names the hosts that are being passed through; use Decrypt again after fixing it.

Network: the device or the Mac is still pointing at the proxy#

Press Disconnect, or run adb shell settings put global http_proxy :0 for Android. For the Mac, open EmuLabZip once: it restores the proxy settings it saved if an earlier run was killed. Otherwise turn the proxies off in System Settings › Network › Details › Proxies.

Network: macOS asks for a password#

Changing the Mac's proxy is a system setting. EmuLabZip tries as you first and asks for administrator rights only if macOS refuses.

Network: a rule does nothing#

Rules see decrypted requests, so HTTPS needs the certificate installed, and a host that rejected it is passed through and cannot be changed. The first enabled rule that matches wins; move the one you expect above the others. A host pattern matches the host only (api.example.com, not https://api.example.com/).

Network: HTTP/3 shows no h3#

The feature is off by default (HTTP/3 → Use HTTP/3 to servers). A host is only tried after one of its responses said it supports HTTP/3, so the first request is always TCP. A network that blocks UDP makes QUIC fail; the host then stays on TCP for 10 minutes.

Layout: nothing to read on iOS#

Simulator.app has to be open on that device, and the program running EmuLabZip has to be allowed in System Settings, Privacy & Security, Accessibility (the app, or your terminal for emulabzip layout). Wake the device if it shows a black screen.

Flutter: "Could not find where the Dart VM service listens"#

Only debug and profile builds have one, and the app writes its address to the log once, when it starts. Start the app again, or give the address from flutter run's output with --uri. A release build has no VM service.

Flutter: the tree has no file names#

The app was not built with --track-widget-creation. flutter run adds it; for flutter build add --extra-front-end-options=--track-widget-creation.

React Native: "Metro is not running" or "does not list a runtime"#

Start Metro (npx react-native start) and open the app on a device that reaches it (adb reverse tcp:8081 tcp:8081 on Android). Metro lists a runtime only while the app is connected to it, and lets one debugger in at a time: close React Native DevTools and Chrome's inspector, then try again. Release builds have no Metro and no React DevTools hook.

State: "RN state is empty" or "no DevTools hook"#

Redux, React Query and contexts are found through React's DevTools hook, which only development builds have. In a release build register stores in globalThis.__EMULABZIP_STORES__ (see React Native state). A store used without a react-redux Provider has to be registered too.

State: restoring or saving fails on Android#

The app has to be debuggable (as for Storage). run-as and tar run on the device: an emulator image with a locked-down run-as cannot save a state. A restore that says the tar was refused found an entry outside the app's folder; the file is not from EmuLabZip, or is damaged.

Edit: "the table cannot be changed"#

A row is found by rowid or by its primary key. A view, or a table without either, has nothing to tell its rows apart: change it with SQL in the app instead. An edit that reads back differently puts the old file back and says so.

Devices: an emulator will not start#

emulabzip avd boot needs the SDK's emulator (found from ANDROID_HOME, ANDROID_SDK_ROOT and the usual folders). Run emulator -avd <name> yourself to see its own message. A running emulator is never wiped or deleted: shut it down first.

Audit: "the area could not be read"#

The log needs the app to be running, so its lines can be told from the system's: start it and use it, then audit again. Storage on Android needs a debuggable app, as in Storage. Requests come from the proxy (start it on the Network view, or pass --har).

Language: "Android changes the language of one app at a time"#

Android has no way to change a device's language from the shell, only an app's (cmd locale set-app-locales, Android 13 and newer). Pass --app, or pick the app in the toolbar. The iOS Simulator changes language for every app, and each takes it when it starts again.

Text checks: a label is reported that is not cut off#

text-cut-off is a heuristic: a single line whose box was held to the room its container (or the next view in its row) left, and whose text runs to the end of the box. Check it at 130% and 200%; if it fits, ignore it.

Visual: "the screenshots are not the same size"#

They come from different devices, orientations or display sizes. Compare like with like: the same device, orientation and display size (control reset-display puts an Android one back).

Network: a Gradle build cannot download its distribution#

Not an EmuLabZip matter, but it comes up with the demo apps: some networks let curl reach the Gradle servers while Java times out. Download the distribution with curl and put it where Gradle expects it (~/.gradle/wrapper/dists/<name>/<hash>/), or build with a Gradle you already have.

Layout: Android says uiautomator produced nothing#

Some windows forbid it: secure screens, and a few players. Go to another screen and try again. If the device is busy (a boot animation, an ANR dialog) wait a moment.

Sessions: a recording is left as a .partial folder#

The recording was killed before it could pack itself. Nothing is lost: emulabzip session show run.ezsession.partial opens it. Delete the folder, or move it, before you record to the same name again.

Timeline: touches are missing#

Touches are read from the kernel's input device with getevent, so a finger on the emulator window or an event sent through the emulator console is seen. adb shell input tap is injected higher up, inside Android, and is not. iOS does not give the simulator's touches to anything outside it, so there are none there. Record with --taps.

Timeline: the log times are "estimated"#

The recording was made before EmuLabZip 0.10, or the device could not tell its time, so the log's local times were placed by comparing the first line with the start of the recording. They can be off by the difference between the two clocks. Record again for exact times.

Video: "screenrecord made no video"#

Some screens cannot be recorded (secure windows) and a few images do not support screenrecord at all. The message carries what the tool printed. On the iOS Simulator, recordVideo needs the simulator to be booted; if it does not start within 20 seconds, the message says why.

Video: the report has a separate .mp4#

A clip up to 20 MB is part of the HTML file. A bigger one is written next to it as emulabzip-report.mp4, and the file refers to it by that name: move or attach the two together.

Replay: "not in the recording"#

The app asked for something the recording does not hold: another address, another query, a method that was not used, or a request that failed when it was recorded. The proxy answers 504 and lists it under Not recorded (or at the end of emulabzip net --replay). Record again with that request, or add --passthrough to let it reach the server. Matching ignores the order of query parameters and the port, but not the values: an app that adds a timestamp or a random id to every request will always miss.

Replay: WebSockets and some connections fail#

While a recording is replayed, what cannot be answered from a HAR file is refused, so it cannot reach the internet: WebSockets, gRPC calls, apps that do not accept the EmuLabZip certificate, and non-TLS connections the proxy cannot read. Use --passthrough if those must work.

Traces: "Perfetto did not record a trace"#

Perfetto needs Android 9 or newer. If the message names a permission, restart the emulator, or run adb shell setprop persist.traced.enable 1 and record again. A custom configuration with a syntax error is reported by Perfetto itself; check it with adb shell perfetto --txt -c - -o /data/misc/perfetto-traces/test <config.txt.

Traces: a CPU profile fails#

simpleperf only samples apps that are debuggable or profileable, and the app must be running. For the whole system you need an emulator image that allows adb root (not Google Play). "No samples were recorded" means the app did nothing while recording: use it, then record again.

Traces: Instruments says Developer Mode is off#

Run sudo DevToolsSecurity -enable in a terminal, enter your password, and record again. DevToolsSecurity -status shows the current state.

Traces: the download of the trace processor fails#

It comes from github.com/google/perfetto/releases. Behind a proxy, set HTTPS_PROXY. A file that does not match the pinned SHA-256 is discarded and never run. You can still open any Perfetto trace in the Perfetto UI.

Crashes: nothing is listed#

On Android, the system keeps a crash in DropBox and rate-limits repeats, so a looping app is listed less often than it crashes. On the iOS Simulator, macOS writes the .ips report a few seconds after the crash, into ~/Library/Logs/DiagnosticReports; reports of apps that are not in a simulator's folder are not listed. Press Refresh, or run emulabzip crashes.

Crashes: the names are still scrambled#

A mapping is only used for the version of the app it was made for, and the crash says which one that is ("Add the mapping.txt of com.example 1.2.0 (42)"). Add the file with exactly that version: emulabzip mappings add com.example "1.2.0 (42)" mapping.txt. A file of another build would give wrong names, so it is not used. Frames also stay as they are when R8 had no line numbers to keep: add -keepattributes SourceFile,LineNumberTable to the rules of the next build.

Crashes: React Native shows 1:608617 instead of a file#

A release build runs a bundle, and its positions need the source map of that bundle. For Hermes use the composed map, android/app/build/generated/sourcemaps/react/release/index.android.bundle.map, not the packager or compiler ones. It also has to be the map of the build that crashed.

Crashes: iOS shows bare addresses#

Add the .dSYM of the build that crashed (emulabzip mappings add com.example.app "1.2.0 (42)" MyApp.app.dSYM). Its UUID has to match the app's, so a dSYM of another build, even of the same version, is not used. Reading addresses needs a Mac, because it uses atos.

Bug report: no failed requests#

Requests come from the proxy in Network. Start it and connect the device before the bug happens; a report made from a session recorded with --network has them too.

Controls: the location does nothing on a device#

Only emulators accept a new location, through the emulator console. It needs the token in ~/.emulator_console_auth_token, which the emulator creates the first time it runs from your account. Physical devices and simulators of other kinds are not supported for location on Android.

Controls: a notification does not appear on Android#

Notifications are posted from the shell with cmd notification post (tried on Android 14). Turn on notifications for "Android Shell" if the device hides them. The app argument is ignored on Android.

Web pages: my WebView is not listed#

A WebView is listed only when its app calls WebView.setWebContentsDebuggingEnabled(true) (a debug build usually does) and the page is open. Chrome is listed while it is open. The list is read when you open Frameworks and when you press Refresh. On iOS use Safari's Develop menu; see Web pages in apps.

Flows: my touches are not recorded#

Only the touchscreen is read: touch the emulator's own window. Taps sent from EmuLabZip (Interact, Play) or by adb shell input never reach it, and typed text is not recorded. A tap gets the name of the view it hit only when the screen was read in time, which takes two or three seconds after the touch before; the point is kept either way. See Input and flows.

On Android, ask the device to try again with Verify again or emulabzip link verify <app>, then check after a few seconds. A fingerprint mismatch usually means the file lists the release key and the build on the device is signed with the debug key. A domain file that redirects (to www, or from http to https) is refused by both systems. See Deep links.

Network: a script rule does nothing#

A script runs only after its exact bytes were approved (Approve this script in the rule, or emulabzip script approve). Change the file and it has to be approved again. If a script runs but the request is unchanged, the flow's details say what the script wrote or why it failed. See Rule scripts.

Plugins: a plugin cannot be run#

It has to be enabled first, and editing its plugin.json disables it again. A plugin that exits with an error shows the end of its error output. Check that the program in command exists (it is looked up in the plugin's folder, then on the PATH) and that it is executable (chmod +x run.sh).

MCP: the assistant sees no tools#

Run emulabzip mcp by hand and send it an initialize request, as in MCP server. If the client cannot find emulabzip, give it the full path. Standard output carries only the protocol; look at standard error (EMULABZIP_LOG=debug) for what went wrong.

Getting diagnostics#

Start the app or the CLI with EMULABZIP_LOG=debug and include the output when you open an issue.