microg/GmsCore · error · NullPointerException
null tasks are not accepted
Error message
null tasks are not accepted
What it means
Tasks.whenAll(Collection) collects a group of Tasks into one Task that completes when all inputs finish. Null and empty collections are tolerated (producing an already-complete task), but any individual null element inside the collection is rejected with this NullPointerException, since a null Task can never complete and would deadlock the aggregate.
Source
Thrown at play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java:171
task.setResult(result);
return task;
}
/**
* Returns a Task that completes successfully when all of the specified Tasks complete
* successfully. Does not accept nulls.
* <p/>
* The returned Task would fail if any of the provided Tasks fail. The returned Task would be set to canceled if
* any of the provided Tasks is canceled and no failure is detected.
*
* @throws NullPointerException if any of the provided Tasks are null
*/
public static Task<Void> whenAll(Collection<? extends Task<?>> tasks) {
if (tasks == null || tasks.isEmpty()) {
return forResult(null);
}
for (Task<?> task : tasks) {
if (task == null) throw new NullPointerException("null tasks are not accepted");
}
TaskImpl<Void> allTask = new TaskImpl<>();
AtomicInteger finishedTasks = new AtomicInteger(0);
AtomicInteger failedTasks = new AtomicInteger(0);
AtomicReference<Exception> exceptionReference = new AtomicReference<>(null);
AtomicBoolean isCancelled = new AtomicBoolean(false);
for (Task<?> task : tasks) {
task.addOnCompleteListener(Runnable::run, completedTask -> {
if (!completedTask.isSuccessful()) {
if (completedTask.isCanceled()) {
isCancelled.set(true);
} else {
exceptionReference.set(completedTask.getException());
failedTasks.incrementAndGet();
}
}
if (finishedTasks.incrementAndGet() != tasks.size()) return;
Exception exception = exceptionReference.get();View on GitHub (pinned to 157c9d86ac)
Solutions
- Filter nulls before aggregating: tasks.removeIf(Objects::isNull) or stream().filter(Objects::nonNull)
- Fix the producer so every API call returns a valid Task (failed work should be a failed Task, not null)
- Alternatively replace with Tasks.whenAllSuccess/whenAllComplete over a defensively validated collection
Example fix
// before
List<Task<Void>> tasks = new ArrayList<>();
for (String id : ids) tasks.add(upload(id)); // upload() can return null
Tasks.whenAll(tasks); // NPE if any element is null
// after
List<Task<Void>> tasks = new ArrayList<>();
for (String id : ids) {
Task<Void> t = upload(id);
if (t != null) tasks.add(t);
}
Tasks.whenAll(tasks); Defensive patterns
Strategy: validation
Validate before calling
List<Task<?>> safe = new ArrayList<>();
for (Task<?> t : tasks) {
if (t != null) safe.add(t);
}
// then: Tasks.whenAll(safe); Type guard
static List<Task<?>> nonNullTasks(Collection<Task<?>> in) {
return in.stream().filter(Objects::nonNull).collect(Collectors.toList());
} Try / catch
try {
Tasks.whenAll(tasks).await();
} catch (NullPointerException e) {
// a null element slipped in - filter and retry
} catch (ExecutionException | InterruptedException e) {
// per-task failures / interruption
} Prevention
- Never add Task-producing call results without checking for null
- Make producers return failed Tasks (setException) rather than null
- Filter with Objects::isNull before aggregation
- Avoid preallocated ArrayLists with null slots
When it happens
Trigger: Calling Tasks.whenAll(list) where the list contains null entries — typically built by conditionally adding results of Task-returning calls that returned null (e.g. list.add(api.getTask()) with getTask() null), or a fixed-size array with unfilled slots.
Common situations: Building a batch of Firestore/Firebase writes where one request failed to produce a Task; parallelizing uploads with a loop that adds null when a file is missing; passing an ArrayList preallocated with nulls.
Related errors
- null camera target
- location must not be null
- Executor must not be null
- Callable must not be null
- 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/5054ea9a4c1aedf6.
Report an issue: GitHub.