microg/GmsCore · error · IllegalArgumentException
Task must not be null
Error message
Task must not be null
What it means
Tasks.await(task, timeout, unit) validates its input and throws IllegalArgumentException when the task reference is null. A null Task carries no completion state, so blocking on it is meaningless and the method fails fast.
Source
Thrown at play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java:49
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* {@link Task} utility methods.
*/
@PublicApi
public final class Tasks {
/**
* 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
*/View on GitHub (pinned to 157c9d86ac)
Solutions
- Check that the API producing the Task is configured and returning a non-null Task before calling await
- Add an explicit null check on the task argument and handle the null path
- Log/inspect why the producer returned null (init failure, wrong client)
- Use Optional/Objects.requireNonNull around the producer call to surface the real bug
Example fix
// before
Task<User> t = maybeGetUser(); // may return null
User u = Tasks.await(t, 5, TimeUnit.SECONDS);
// after
Task<User> t = maybeGetUser();
if (t != null) {
User u = Tasks.await(t, 5, TimeUnit.SECONDS);
} Defensive patterns
Strategy: validation
Validate before calling
if (task == null) { throw new IllegalStateException("Task producer returned null"); } Type guard
boolean hasTask(Task<?> t) { return t != null; } Try / catch
try {
T r = Tasks.await(task, 5, TimeUnit.SECONDS);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Task must not be null")) { /* handle null producer */ }
} Prevention
- Never allow task-producing APIs to return null; fail at the source
- Objects.requireNonNull(task) immediately after obtaining it
- Enable nullability annotations/lint to catch null Tasks at compile time
- Log producer errors when a Task is unexpectedly absent
When it happens
Trigger: Calling Tasks.await(null, timeout, unit) — typically when a preceding async call returned null instead of a Task.
Common situations: Misconfigured initialization of the underlying task source returning null; unchecked return value of a factory method; Kotlin/Java interop where a platform type hid the nullability.
Related errors
- Timeout must be positive
- TimeUnit must not be null
- Timed out waiting for Task
- Must not be invoked on main thread
- deleteAll was set to true but keys were also provided
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/bbac3da3a0d75277.
Report an issue: GitHub.