greenrobot/greenDAO · error · DaoException

Internal error: peeked op did not match removed op

Error message

Internal error: peeked op did not match removed op

What it means

During transaction merging, AsyncOperationExecutor peeks the queue head and then removes it, expecting the same operation. If remove() returns a different op than peek() saw, the queue's internal consistency is broken — greendao's own comment calls it a paranoia check for broken threading. This indicates a concurrency bug (queue mutated by another thread during merge).

Solutions

  1. Serialize async access: issue async operations from a single thread, or guard enqueue calls with your own synchronization.
  2. Check your greendao version and upgrade — this path was hardened in later releases.
  3. If reproducible, file a bug with a thread dump; do not attempt to work around it by catching it.
  4. Reduce use of mergeable multi-op transactions (e.g. many insertInTxAsync calls) from different threads.

Example fix

// before
// async ops enqueued from multiple worker threads on the same asyncSession
new Thread(() -> asyncSession.insert(a)).start();
new Thread(() -> asyncSession.insert(b)).start();
// after
// funnel all async ops through one thread/executor
singleThreadExecutor.execute(() -> asyncSession.insert(a));
singleThreadExecutor.execute(() -> asyncSession.insert(b));
Defensive patterns

Strategy: fallback

Validate before calling

// enqueue all async ops for a session from a single thread:
Executor asyncEnqueuer = Executors.newSingleThreadExecutor();
if (!asyncEnqueuer.isShutdown()) { asyncEnqueuer.execute(() -> session.insert(e)); }

Prevention

When it happens

Trigger: Multiple threads concurrently enqueueing/removing operations on the same AsyncOperationExecutor while a transaction merge (mergeable ops like InsertInTxIterable) is in progress, or misuse of the executor's internal queue from outside its design.

Common situations: Rare; usually means the app is sharing an AsyncSession/executor across threads in a way greendao didn't anticipate, or a greendao version bug in the merge path.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of greenrobot/greenDAO@0bbb338e17 (2026-09-08). Data as JSON: /api/errors/c50d982ac49e704c. Report an issue: GitHub.

Appendix: source

Thrown at DaoCore/src/main/java/org/greenrobot/greendao/async/AsyncOperationExecutor.java:201

        Database db = operation1.getDatabase();
        db.beginTransaction();
        boolean success = false;
        try {
            for (int i = 0; i < mergedOps.size(); i++) {
                AsyncOperation operation = mergedOps.get(i);
                executeOperation(operation);
                if (operation.isFailed()) {
                    // Operation may still have changed the DB, roll back everything
                    break;
                }
                if (i == mergedOps.size() - 1) {
                    AsyncOperation peekedOp = queue.peek();
                    if (i < maxOperationCountToMerge && operation.isMergeableWith(peekedOp)) {
                        AsyncOperation removedOp = queue.remove();
                        if (removedOp != peekedOp) {
                            // Paranoia check, should not occur unless threading is broken
                            throw new DaoException("Internal error: peeked op did not match removed op");
                        }
                        mergedOps.add(removedOp);
                    } else {
                        // No more ops in the queue to merge, finish it
                        db.setTransactionSuccessful();
                        success = true;
                        break;
                    }
                }
            }
        } finally {
            try {
                db.endTransaction();
            } catch (RuntimeException e) {
                DaoLog.i("Async transaction could not be ended, success so far was: " + success, e);
                success = false;
            }
        }

View on GitHub (pinned to 0bbb338e17)