Tencent/matrix · error · RuntimeException
Did not expect thread to be interrupted
Error message
Did not expect thread to be interrupted
What it means
FutureResult.wait wraps CountDownLatch.await and treats InterruptedException as a programming error: the dumping thread is not expected to be interrupted while waiting for the heap-dump worker. When the waiting thread's interrupt flag is set, it rethrows as RuntimeException('Did not expect thread to be interrupted'). This keeps leak-detection logic simple by assuming no cooperative cancellation.
Solutions
- Avoid interrupting the thread performing the heap dump; use a cooperative cancel flag instead.
- Ensure dumpHeap runs on a dedicated thread not subject to shutdownNow() interrupts.
- If interruption is legitimate in your flow, call wait inside a try-catch for RuntimeException and treat it as 'dump aborted'.
- Check that no other component (watchdog, leak cancel API) interrupts this thread concurrently.
Example fix
// before threadPool.shutdownNow(); // interrupts in-flight dump // after dumpFuture.cancel(false); // let running dump finish, then shutdown
Defensive patterns
Strategy: try-catch
Validate before calling
if (Thread.currentThread().isInterrupted()) {
// clear/defer interrupt before calling wait
Thread.interrupted();
} Try / catch
try {
boolean ok = futureResult.wait(10, TimeUnit.SECONDS);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("interrupted")) {
// treat as dump aborted; restore interrupt status
Thread.currentThread().interrupt();
}
} Prevention
- Never shutdownNow()/interrupt the thread performing heap dumps
- Use cooperative cancel flags instead of interrupts
- Run dumps on a dedicated executor isolated from lifecycle shutdown
When it happens
Trigger: Calling wait(timeout, unit) (from dumpHeap) after the waiting thread has been interrupted, e.g. Thread.interrupt() issued by an executor shutdown, Activity destroy path, or watchdog canceling the dump.
Common situations: App shutting down or ViewModel/Activity being destroyed while a heap dump is in flight; executor.shutdownNow() interrupting worker threads; a developer canceling a dump task with future.cancel(true).
Related errors
- sdkVersion is absent in result.info.
- manufacturer is absent in result.info.
- hprofEntry is absent in result.info.
- leakedActivityKey is absent in result.info.
- Unable to determine bitmap configuration
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/9797ac8a0a24a0ff.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-android/src/main/java/com/tencent/matrix/resource/leakcanary/internal/FutureResult.java:36
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public final class FutureResult<T> {
private final AtomicReference<T> resultHolder;
private final CountDownLatch latch;
public FutureResult() {
resultHolder = new AtomicReference<>();
latch = new CountDownLatch(1);
}
public boolean wait(long timeout, TimeUnit unit) {
try {
return latch.await(timeout, unit);
} catch (InterruptedException e) {
throw new RuntimeException("Did not expect thread to be interrupted", e);
}
}
public T get() {
if (latch.getCount() > 0) {
throw new IllegalStateException("Call wait() and check its result");
}
return resultHolder.get();
}
public void set(T result) {
resultHolder.set(result);
latch.countDown();
}
}
View on GitHub (pinned to 3b8293bd65)