microg/GmsCore · error · IllegalStateException

Task is not yet complete

Error message

Task is not yet complete

What it means

TaskImpl.getResult() returns the task's result only after completion; the check order is: not-completed, cancelled, failed, then success. If you call getResult() while the Task is still pending, it throws this IllegalStateException because there is no result yet — this is a misuse of the API rather than a task failure.

Source

Thrown at play-services-tasks/src/main/java/org/microg/gms/tasks/TaskImpl.java:129

    @Override
    public <TContinuationResult> Task<TContinuationResult> continueWithTask(Executor executor, Continuation<TResult, Task<TContinuationResult>> continuation) {
        ContinuationWithExecutor<TResult, TContinuationResult> c = new ContinuationWithExecutor<>(executor, continuation);
        enqueueOrInvoke(c);
        return c.getTask();
    }

    @Override
    public Exception getException() {
        synchronized (lock) {
            return exception;
        }
    }

    @Override
    public TResult getResult() {
        synchronized (lock) {
            if (!completed) throw new IllegalStateException("Task is not yet complete");
            if (cancelled) throw new CancellationException("Task is canceled");
            if (exception != null) throw new RuntimeExecutionException(exception);
            return result;
        }
    }

    @Override
    public <X extends Throwable> TResult getResult(Class<X> exceptionType) throws X {
        synchronized (lock) {
            if (!completed) throw new IllegalStateException("Task is not yet complete");
            if (cancelled) throw new CancellationException("Task is canceled");
            if (exceptionType.isInstance(exception)) throw exceptionType.cast(exception);
            if (exception != null) throw new RuntimeExecutionException(exception);
            return result;
        }
    }

    @Override

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Use the completion value: on a background thread call TResult r = Tasks.await(task) and use its return value, not task.getResult()
  2. On the main thread, read the result inside addOnSuccessListener/addOnCompleteListener callbacks
  3. If you must call getResult(), guard it with if (task.isComplete() && task.isSuccessful()) first

Example fix

// before
Task<QuerySnapshot> task = db.collection("c").get();
QuerySnapshot snap = task.getResult(); // IllegalStateException: not yet complete
// after
Task<QuerySnapshot> task = db.collection("c").get();
// background thread:
QuerySnapshot snap = Tasks.await(task);
// or main thread:
task.addOnSuccessListener(s -> useResult(s));
Defensive patterns

Strategy: try-catch

Validate before calling

if (!task.isComplete()) {
    // not ready - await it (background thread) or use a listener (main thread)
    TResult r = Tasks.await(task); // off main thread only
}

Type guard

static <T> boolean hasResult(Task<T> t) {
    return t.isComplete() && t.isSuccessful();
}

Try / catch

try {
    T result = Tasks.await(task); // never call task.getResult() on a pending task
} catch (IllegalStateException e) {
    // should not happen via await(); guard with isComplete() if calling getResult() directly
} catch (ExecutionException e) {
    // task failure
}

Prevention

When it happens

Trigger: Calling task.getResult() directly after starting an async operation (e.g. right after a Firestore get()/Firebase auth call) without first awaiting completion via Tasks.await(), addOnCompleteListener, or checking isComplete().

Common situations: Forgetting Tasks.await() on a background thread; calling getResult() inside code that assumed synchronous behavior after migrating from blocking APIs; reading the result in a listener registered before completion instead of inside the completion callback; ignoring the return value of Tasks.await and using the original task.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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