greenrobot/greenDAO · error · DaoException

Method may be called only in owner thread, use…

Error message

Method may be called only in owner thread, use forCurrentThread to get an instance for this thread

What it means

greenDAO Query objects are bound to the thread that created them (ownerThread). checkThread() throws DaoException if any mutation (setParameter, setLimit, etc.) is invoked from another thread. This protects internal parameter arrays from cross-thread mutation.

Solutions

  1. Call query.forCurrentThread() to obtain a thread-local copy before mutating or executing
  2. Create a fresh Query in the thread that will use it
  3. Instead of setParameter, use the thread-safe variant that takes and re-binds via forCurrentThread with new parameter values

Example fix

// before
Query<User> query = userDao.queryBuilder().build(); // created on thread A
// later on thread B
query.setParameter(0, "foo"); // throws
// after
Query<User> query = userDao.queryBuilder().build();
Query<User> queryForThisThread = query.forCurrentThread();
queryForThisThread.setParameter(0, "foo");
Defensive patterns

Strategy: type-guard

Validate before calling

if (query.getOwnerThread() != Thread.currentThread()) {
    query = query.forCurrentThread();
}

Type guard

function isOwnerThread(query) { return Thread.currentThread() === query.getOwnerThread(); }

Try / catch

try {
    query.setParameter(index, value);
} catch (DaoException e) {
    if (e.getMessage().contains("forCurrentThread")) {
        query = query.forCurrentThread();
        query.setParameter(index, value);
    }
}

Prevention

When it happens

Trigger: Creating a Query on a background/loader thread and later calling setParameter/setLimit/setOffset on it from a different thread (e.g. UI thread or an AsyncTask worker differing from the creator).

Common situations: Caching a Query in a singleton and reusing it across threads; using the same Query in multiple AsyncTask executions; Android loader vs UI thread mismatches.

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 greenrobot/greenDAO@0bbb338e17 (2026-09-08). Data as JSON: /api/errors/f97e67820ee6fd9d. Report an issue: GitHub.

Appendix: source

Thrown at DaoCore/src/main/java/org/greenrobot/greendao/query/AbstractQuery.java:99

    /**
     * @see #setParameter(int, Object)
     */
    public AbstractQuery<T> setParameter(int index, Date parameter) {
        Long converted = parameter != null ? parameter.getTime() : null;
        return setParameter(index, converted);
    }

    /**
     * @see #setParameter(int, Object)
     */
    public AbstractQuery<T> setParameter(int index, Boolean parameter) {
        Integer converted = parameter != null ? (parameter ? 1 : 0) : null;
        return setParameter(index, converted);
    }

    protected void checkThread() {
        if (Thread.currentThread() != ownerThread) {
            throw new DaoException(
                    "Method may be called only in owner thread, use forCurrentThread to get an instance for this thread");
        }
    }

}

View on GitHub (pinned to 0bbb338e17)