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

  1. Filter nulls before aggregating: tasks.removeIf(Objects::isNull) or stream().filter(Objects::nonNull)
  2. Fix the producer so every API call returns a valid Task (failed work should be a failed Task, not null)
  3. 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

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


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/5054ea9a4c1aedf6. Report an issue: GitHub.