microg/GmsCore · error · TimeoutException
Timed out waiting for Task
Error message
Timed out waiting for Task
What it means
When the task does not complete within the given timeout, Tasks.await(task, timeout, unit) stops waiting on the latch and throws TimeoutException('Timed out waiting for Task'). This is a checked exception signaling the operation took too long, not that it failed.
Source
Thrown at play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java:58
/**
* Blocks until the specified Task is complete.
*
* @return the Task's result
* @throws ExecutionException if the Task fails
* @throws InterruptedException if an interrupt occurs while waiting for the Task to complete
* @throws TimeoutException if the specified timeout is reached before the Task completes
*/
public static <TResult> TResult await(Task<TResult> task, long timeout, TimeUnit unit) throws ExecutionException, InterruptedException, TimeoutException {
if (task == null) throw new IllegalArgumentException("Task must not be null");
if (timeout <= 0) throw new IllegalArgumentException("Timeout must be positive");
if (unit == null) throw new IllegalArgumentException("TimeUnit must not be null");
if (task.isComplete()) return handleCompletedTask(task);
CountDownLatch latch = new CountDownLatch(1);
task.addOnCompleteListener(Runnable::run, completedTask -> latch.countDown());
if (latch.await(timeout, unit)) {
return handleCompletedTask(task);
}
throw new TimeoutException("Timed out waiting for Task");
}
/**
* Blocks until the specified Task is complete.
*
* @return the Task's result
* @throws ExecutionException if the Task fails
* @throws InterruptedException if an interrupt occurs while waiting for the Task to complete
*/
public static <TResult> TResult await(Task<TResult> task) throws ExecutionException, InterruptedException {
if (Looper.getMainLooper().getThread() == Thread.currentThread())
throw new IllegalStateException("Must not be invoked on main thread");
if (task == null) throw new IllegalArgumentException("Task must not be null");
if (task.isComplete()) return handleCompletedTask(task);
CountDownLatch latch = new CountDownLatch(1);
task.addOnCompleteListener(Runnable::run, completedTask -> latch.countDown());
latch.await();
return handleCompletedTask(task);View on GitHub (pinned to 157c9d86ac)
Solutions
- Increase the timeout to a realistic bound for the operation
- Use the unbounded Tasks.await(task) overload on a background thread when there is no deadline
- Cancel/abandon the work gracefully and retry with backoff on TimeoutException
- Verify the task's completion listener can actually run (executor alive, process not blocked) so the latch counts down
Example fix
// before
T r = Tasks.await(task, 500, TimeUnit.MILLISECONDS); // too short
// after
try {
T r = Tasks.await(task, 30, TimeUnit.SECONDS);
} catch (TimeoutException e) {
// retry or surface timeout to caller
} Defensive patterns
Strategy: try-catch
Validate before calling
// estimate: skip await when deadline already passed
if (timeoutMs <= 0) throw new TimeoutException("deadline already passed"); Try / catch
try {
T r = Tasks.await(task, timeout, unit);
} catch (TimeoutException e) {
// cancel UI spinner, retry with backoff, or surface timeout
} catch (ExecutionException e) {
// task itself failed
} Prevention
- Size timeouts from measured p95 latencies, not guesses
- Catch TimeoutException separately from ExecutionException to distinguish slow vs failed
- Add retry-with-backoff around transient operations
- Use bounded waits plus explicit cancellation instead of unbounded blocking
When it happens
Trigger: Calling the timed-overload with a timeout shorter than the task's actual duration: slow network calls, large payloads, stalled backend, or a task whose listener was registered on a dead executor so the latch never counts down.
Common situations: Mobile networks with high latency; too-aggressive timeout constants in config; background work exceeding UI-driven deadlines; debugger breakpoints pausing the completing thread.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timeout must be positive
- Task must not be null
- TimeUnit must not be null
- Must not be invoked on main thread
- ERROR_TIMEOUT
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/0341d277e47706c5.
Report an issue: GitHub.