MuntashirAkon/AppManager · error · java.net.SocketTimeoutException

Timed out waiting for ADB command

Error message

Timed out waiting for ADB command: ${command}

What it means

LocalServerManager.executeAdbCommand sends a command over the ADB shell stream and uses a CountDownLatch (commandWatcher) that is counted down when success/failure markers are seen on the output. If neither marker arrives within the timeout, it throws SocketTimeoutException, meaning the remote shell never produced the expected output.

Solutions

  1. Increase the timeout (timeout/timeoutUnit arguments) to accommodate slow devices
  2. Verify the command is valid and produces output matching successPrefix
  3. Re-check ADB connectivity (openAdbShell again) since the stream may have died
  4. Retry the command; transient wireless-debugging drops often resolve on a second attempt

Example fix

// before
serverManager.executeAdbCommand(cmd, 10, TimeUnit.SECONDS);
// after
try {
    serverManager.executeAdbCommand(cmd, 30, TimeUnit.SECONDS);
} catch (SocketTimeoutException e) {
    // reconnect ADB shell and retry once
}
Defensive patterns

Strategy: retry

Validate before calling

// ensure shell stream is alive and command is well-formed first
if (!shellStream.isClosed()) {
    sendKeepAlive(); // e.g. write "id\n" and check the success prefix before the real command
}

Try / catch

try {
    result = executeAdbCommand(cmd, timeout, unit);
} catch (SocketTimeoutException e) {
    // reconnect the ADB shell and retry once with a longer timeout
}

Prevention

When it happens

Trigger: Calling executeAdbCommand when the ADB shell is hung or the daemon dies mid-command, the command blocks indefinitely (e.g. waiting on input), or output parsing never sees the success prefix within the configured timeout.

Common situations: Device under heavy load making the shell slow; ADB stream silently dropped (wireless debugging hiccup); command producing unexpected output so the success/failure prefix is never matched; timeout set too low.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/0340250ab35cba13. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/servermanager/LocalServerManager.java:323

                    }
                    if (response.startsWith("Error!")) {
                        readFailure.set(new IOException(response));
                        break;
                    }
                }
            } catch (Throwable e) {
                readFailure.set(e);
            } finally {
                commandWatcher.countDown();
            }
        }, "am-adb-command-output");
        outputThread.start();
        try {
            outputStream.write("id\n".getBytes(StandardCharsets.UTF_8));
            outputStream.write((command + "\n").getBytes(StandardCharsets.UTF_8));
            outputStream.flush();
            if (!commandWatcher.await(timeout, timeoutUnit)) {
                throw new SocketTimeoutException("Timed out waiting for ADB command: " + command);
            }
            if (!commandSucceeded.get()) {
                Throwable failure = readFailure.get();
                throw new IOException("ADB command did not produce " + successPrefix, failure);
            }
        } finally {
            outputThread.interrupt();
        }
    }

    @WorkerThread
    private void useRootStartServer() throws Exception {
        if (!Ops.hasRoot()) {
            throw new Exception("Root access denied");
        }
        String command = ServerConfig.getServerRunnerCommand();
        // + "\n" + "supolicy --live 'allow qti_init_shell zygote_exec file execute'";
        Log.d(TAG, "useRootStartServer: %s", command);

View on GitHub (pinned to 0152f468fc)