{"record":{"id":"448d3bdd2d8aba99","repo":"microg/GmsCore","slug":"task-is-not-yet-complete","errorCode":null,"errorMessage":"Task is not yet complete","messagePattern":"Task is not yet complete","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"play-services-tasks/src/main/java/org/microg/gms/tasks/TaskImpl.java","lineNumber":129,"sourceCode":"\n    @Override\n    public <TContinuationResult> Task<TContinuationResult> continueWithTask(Executor executor, Continuation<TResult, Task<TContinuationResult>> continuation) {\n        ContinuationWithExecutor<TResult, TContinuationResult> c = new ContinuationWithExecutor<>(executor, continuation);\n        enqueueOrInvoke(c);\n        return c.getTask();\n    }\n\n    @Override\n    public Exception getException() {\n        synchronized (lock) {\n            return exception;\n        }\n    }\n\n    @Override\n    public TResult getResult() {\n        synchronized (lock) {\n            if (!completed) throw new IllegalStateException(\"Task is not yet complete\");\n            if (cancelled) throw new CancellationException(\"Task is canceled\");\n            if (exception != null) throw new RuntimeExecutionException(exception);\n            return result;\n        }\n    }\n\n    @Override\n    public <X extends Throwable> TResult getResult(Class<X> exceptionType) throws X {\n        synchronized (lock) {\n            if (!completed) throw new IllegalStateException(\"Task is not yet complete\");\n            if (cancelled) throw new CancellationException(\"Task is canceled\");\n            if (exceptionType.isInstance(exception)) throw exceptionType.cast(exception);\n            if (exception != null) throw new RuntimeExecutionException(exception);\n            return result;\n        }\n    }\n\n    @Override","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-tasks/src/main/java/org/microg/gms/tasks/TaskImpl.java#L111-L147","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","solutions":["Use the completion value: on a background thread call TResult r = Tasks.await(task) and use its return value, not task.getResult()","On the main thread, read the result inside addOnSuccessListener/addOnCompleteListener callbacks","If you must call getResult(), guard it with if (task.isComplete() && task.isSuccessful()) first"],"exampleFix":"// before\nTask<QuerySnapshot> task = db.collection(\"c\").get();\nQuerySnapshot snap = task.getResult(); // IllegalStateException: not yet complete\n// after\nTask<QuerySnapshot> task = db.collection(\"c\").get();\n// background thread:\nQuerySnapshot snap = Tasks.await(task);\n// or main thread:\ntask.addOnSuccessListener(s -> useResult(s));","handlingStrategy":"try-catch","validationCode":"if (!task.isComplete()) {\n    // not ready - await it (background thread) or use a listener (main thread)\n    TResult r = Tasks.await(task); // off main thread only\n}","typeGuard":"static <T> boolean hasResult(Task<T> t) {\n    return t.isComplete() && t.isSuccessful();\n}","tryCatchPattern":"try {\n    T result = Tasks.await(task); // never call task.getResult() on a pending task\n} catch (IllegalStateException e) {\n    // should not happen via await(); guard with isComplete() if calling getResult() directly\n} catch (ExecutionException e) {\n    // task failure\n}","preventionTips":["Never treat Task<T> as a synchronous value holder; always await or listen","Use the value returned by Tasks.await(), not task.getResult(), after awaiting","Read results only inside addOnSuccessListener/addOnCompleteListener on the main thread","Gate direct getResult() calls behind isComplete() && isSuccessful()"],"tags":["android","async","illegal-state","task-lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}