{"record":{"id":"f97e67820ee6fd9d","repo":"greenrobot/greenDAO","slug":"method-may-be-called-only-in-owner-thread-use-for","errorCode":null,"errorMessage":"Method may be called only in owner thread, use forCurrentThread to get an instance for this thread","messagePattern":"Method may be called only in owner thread, use forCurrentThread to get an instance for this thread","errorType":"exception","errorClass":"DaoException","httpStatus":null,"severity":"error","filePath":"DaoCore/src/main/java/org/greenrobot/greendao/query/AbstractQuery.java","lineNumber":99,"sourceCode":"    /**\n     * @see #setParameter(int, Object)\n     */\n    public AbstractQuery<T> setParameter(int index, Date parameter) {\n        Long converted = parameter != null ? parameter.getTime() : null;\n        return setParameter(index, converted);\n    }\n\n    /**\n     * @see #setParameter(int, Object)\n     */\n    public AbstractQuery<T> setParameter(int index, Boolean parameter) {\n        Integer converted = parameter != null ? (parameter ? 1 : 0) : null;\n        return setParameter(index, converted);\n    }\n\n    protected void checkThread() {\n        if (Thread.currentThread() != ownerThread) {\n            throw new DaoException(\n                    \"Method may be called only in owner thread, use forCurrentThread to get an instance for this thread\");\n        }\n    }\n\n}\n","sourceCodeStart":81,"sourceCodeEnd":105,"githubUrl":"https://github.com/greenrobot/greenDAO/blob/0bbb338e17c4cf28aba5aae62d42f73f50186157/DaoCore/src/main/java/org/greenrobot/greendao/query/AbstractQuery.java#L81-L105","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Call query.forCurrentThread() to obtain a thread-local copy before mutating or executing","Create a fresh Query in the thread that will use it","Instead of setParameter, use the thread-safe variant that takes and re-binds via forCurrentThread with new parameter values"],"exampleFix":"// before\nQuery<User> query = userDao.queryBuilder().build(); // created on thread A\n// later on thread B\nquery.setParameter(0, \"foo\"); // throws\n// after\nQuery<User> query = userDao.queryBuilder().build();\nQuery<User> queryForThisThread = query.forCurrentThread();\nqueryForThisThread.setParameter(0, \"foo\");","handlingStrategy":"type-guard","validationCode":"if (query.getOwnerThread() != Thread.currentThread()) {\n    query = query.forCurrentThread();\n}","typeGuard":"function isOwnerThread(query) { return Thread.currentThread() === query.getOwnerThread(); }","tryCatchPattern":"try {\n    query.setParameter(index, value);\n} catch (DaoException e) {\n    if (e.getMessage().contains(\"forCurrentThread\")) {\n        query = query.forCurrentThread();\n        query.setParameter(index, value);\n    }\n}","preventionTips":["Always call forCurrentThread() before reusing a cached Query","Create queries in the same thread that executes them","Avoid storing Query instances in shared singletons","On Android, obtain per-thread queries inside the worker/AsyncTask"],"tags":["greendao","orm","threading","concurrency"],"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"}