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

  1. Add .limit(n) in the QueryBuilder before build() so the LIMIT parameter slot exists
  2. Rebuild the Query with QueryBuilder when the limit requirement changes
  3. 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

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


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)