greenrobot/greenDAO · error · IllegalStateException
Limit must be set with QueryBuilder before it can be used…
Error message
Limit must be set with QueryBuilder before it can be used here
What it means
setLimit only rewrites an existing LIMIT placeholder parameter. If the Query was built without QueryBuilder.limit(int), limitPosition is -1 and there is no slot to write, so IllegalStateException is thrown.
Solutions
- Add .limit(n) in the QueryBuilder before build() so the LIMIT parameter slot exists
- Rebuild the Query with QueryBuilder when the limit requirement changes
- Keep a cached QueryBuilder rather than only the built Query if limits vary at runtime
Example fix
// before Query<User> q = userDao.queryBuilder().where(...).build(); q.setLimit(10); // throws // after Query<User> q = userDao.queryBuilder().where(...).limit(10).build(); q.setLimit(10); // OK: adjusts existing limit
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the query was built with .limit() — track at build time Query<User> q = qb.where(...).limit(initialLimit).build();
Try / catch
try {
query.setLimit(newLimit);
} catch (IllegalStateException e) {
if (e.getMessage().contains("Limit must be set with QueryBuilder")) {
query = qb.where(...).limit(newLimit).build();
}
} Prevention
- Always add .limit() in the builder if you plan to change limits later
- Rebuild queries when pagination requirements change
- Cache the QueryBuilder, not only the built Query
When it happens
Trigger: Calling query.setLimit(n) on a Query created by queryBuilder()...build() where .limit() was never invoked during building.
Common situations: Attempting to adjust paging dynamically after building a query; copying query-building code that omitted .limit(); changing requirements from unpaginated to paginated queries.
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
- Offset 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/e0ab72e67e566af6.
Report an issue: GitHub.
Appendix: source
Thrown at DaoCore/src/main/java/org/greenrobot/greendao/query/AbstractQueryWithLimit.java:57
* Sets the parameter (0 based) using the position in which it was added during building the query. Note: all
* standard WHERE parameters come first. After that come the WHERE parameters of joins (if any).
*/
public AbstractQueryWithLimit<T> setParameter(int index, Object parameter) {
if (index >= 0 && (index == limitPosition || index == offsetPosition)) {
throw new IllegalArgumentException("Illegal parameter index: " + index);
}
return (AbstractQueryWithLimit<T>) super.setParameter(index, parameter);
}
/**
* Sets the limit of the maximum number of results returned by this Query. {@link
* org.greenrobot.greendao.query.QueryBuilder#limit(int)} must
* 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)