greenrobot/greenDAO · error · IllegalStateException
Offset must be set with QueryBuilder before it can be used…
Error message
Offset must be set with QueryBuilder before it can be used here
What it means
setOffset only rewrites an existing OFFSET placeholder parameter. If the Query was built without QueryBuilder.offset(int), offsetPosition is -1 and IllegalStateException is thrown because there is no OFFSET slot in the prepared SQL.
Solutions
- Include .offset(n) in the QueryBuilder before build() so the OFFSET parameter slot exists
- Rebuild the query with the desired initial offset when paging requirements change
- Prefer setLimit + setOffset on a query built with both limit and offset for paging
Example fix
// before Query<User> q = userDao.queryBuilder().where(...).limit(20).build(); q.setOffset(20); // throws // after Query<User> q = userDao.queryBuilder().where(...).limit(20).offset(0).build(); q.setOffset(20); // OK
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the query was built with .offset() Query<User> q = qb.where(...).limit(pageSize).offset(0).build();
Try / catch
try {
query.setOffset(newOffset);
} catch (IllegalStateException e) {
if (e.getMessage().contains("Offset must be set with QueryBuilder")) {
query = qb.where(...).limit(pageSize).offset(newOffset).build();
}
} Prevention
- Seed .offset(0) in the builder when doing incremental paging
- Pair .limit() with .offset() whenever paging is planned
- Rebuild the Query if offset support is needed later
When it happens
Trigger: Calling query.setOffset(n) on a Query built without .offset() in the QueryBuilder chain.
Common situations: Implementing incremental paging (moving OFFSET) but forgetting to seed the initial offset in the builder; refactoring queries from fixed to dynamic offsets.
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
- Limit must be set with QueryBuilder before it can be used…
- Table alias required
- Illegal parameter index:
- Expected unique result, but count was
- Duplicate property ordinals
AI-assisted analysis of greenrobot/greenDAO@0bbb338e17 (2026-09-08).
Data as JSON: /api/errors/6498945806a3ae49.
Report an issue: GitHub.
Appendix: source
Thrown at DaoCore/src/main/java/org/greenrobot/greendao/query/AbstractQueryWithLimit.java:70
* have been called on the QueryBuilder that created this Query object.
*/
public void setLimit(int limit) {
checkThread();
if (limitPosition == -1) {
throw new IllegalStateException("Limit must be set with QueryBuilder before it can be used here");
}
parameters[limitPosition] = Integer.toString(limit);
}
/**
* Sets the offset for results returned by this Query. {@link org.greenrobot.greendao.query.QueryBuilder#offset(int)} must
* have been called on
* the QueryBuilder that created this Query object.
*/
public void setOffset(int offset) {
checkThread();
if (offsetPosition == -1) {
throw new IllegalStateException("Offset must be set with QueryBuilder before it can be used here");
}
parameters[offsetPosition] = Integer.toString(offset);
}
}
View on GitHub (pinned to 0bbb338e17)