{"record":{"id":"717816acd96a6ca7","repo":"greenrobot/greenDAO","slug":"this-operation-did-not-yet-complete","errorCode":null,"errorMessage":"This operation did not yet complete","messagePattern":"This operation did not yet complete","errorType":"exception","errorClass":"DaoException","httpStatus":null,"severity":"error","filePath":"DaoCore/src/main/java/org/greenrobot/greendao/async/AsyncOperation.java","lineNumber":137,"sourceCode":"    /**\n     * @return true if this operation is mergeable with the given operation. Checks for null, {@link #FLAG_MERGE_TX},\n     * and if the database instances match.\n     */\n    boolean isMergeableWith(AsyncOperation other) {\n        return other != null && isMergeTx() && other.isMergeTx() && getDatabase() == other.getDatabase();\n    }\n\n    public long getTimeStarted() {\n        return timeStarted;\n    }\n\n    public long getTimeCompleted() {\n        return timeCompleted;\n    }\n\n    public long getDuration() {\n        if (timeCompleted == 0) {\n            throw new DaoException(\"This operation did not yet complete\");\n        } else {\n            return timeCompleted - timeStarted;\n        }\n    }\n\n    public boolean isFailed() {\n        return throwable != null;\n    }\n\n    public boolean isCompleted() {\n        return completed;\n    }\n\n    /**\n     * Waits until the operation is complete. If the thread gets interrupted, any {@link InterruptedException} will be\n     * rethrown as a {@link DaoException}.\n     *\n     * @return Result if any, see {@link #getResult()}","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/greenrobot/greenDAO/blob/0bbb338e17c4cf28aba5aae62d42f73f50186157/DaoCore/src/main/java/org/greenrobot/greendao/async/AsyncOperation.java#L119-L155","documentation":"AsyncOperation.getDuration() computes timeCompleted - timeStarted, but the operation timestamps are only set when the async executor finishes the operation. If the operation has not completed yet, timeCompleted is 0 and the method throws this DaoException instead of returning a bogus negative duration.","triggerScenarios":"Calling getDuration() on an AsyncOperation object obtained from AsyncSession (e.g. insertAsync/insertInTxAsync return ops or listeners) before the operation has executed on the AsyncOperationExecutor thread — i.e. before isOperationCompleted()/waitForCompletion() returns.","commonSituations":"Developers query timing right after enqueueing an async insert, or in code that runs concurrently with the operation, e.g. measuring performance immediately after submit instead of in the completion listener.","solutions":["Wait for completion before asking for the duration: call operation.waitForCompletion() or check operation.isOperationCompleted() first.","Only compute timing inside the AsyncOperationListener's onOperationCompleted callback.","If you need elapsed time regardless, track System.currentTimeMillis() yourself around the enqueue call."],"exampleFix":"// before\nAsyncOperation op = asyncSession.insert(entity);\nlong duration = op.getDuration(); // throws if not done\n// after\nAsyncOperation op = asyncSession.insert(entity);\nop.waitForCompletion();\nlong duration = op.getDuration();","handlingStrategy":"validation","validationCode":"if (!op.isOperationCompleted()) {\n    throw new IllegalStateException(\"wait for the async operation before calling getDuration()\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    long d = op.getDuration();\n} catch (DaoException e) {\n    // op not completed yet: wait or skip timing\n    op.waitForCompletion();\n    long d = op.getDuration();\n}","preventionTips":["Call waitForCompletion() or check isOperationCompleted() before reading timing data","Measure durations from the onOperationCompleted listener callback","Never call getDuration() immediately after enqueueing an async operation"],"tags":["async","lifecycle","greendao"],"backgroundTag":"invalid-state-transition","analyzedSha":"0bbb338e17c4cf28aba5aae62d42f73f50186157","analyzedAt":"2026-09-08T03:22:36.050Z","contentChangedAt":"2026-09-08T03:22:36.050Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}