flowable/flowable-engine · error · ActivitiException
Query return " + results.size() + " results instead of max 1
Error message
Query return " + results.size() + " results instead of max 1
What it means
AbstractNativeQuery.executeSingleResult() backs nativeQuery().singleResult(). If executeList returns more than one row it throws plain ActivitiException "Query return N results instead of max 1", because singleResult() has a stricter contract: exactly one row expected. This is a query-contract violation, not an argument error.
Solutions
- Tighten the native query WHERE clause so it can match at most one row (filter by primary key/unique column).
- Use list() / listPage(0, 1) instead of singleResult() when multiple matches are legitimate, and pick the first.
- Add a deterministic ORDER BY + limiting filter if the newest/oldest row is wanted (e.g. RES_ID_ = ? or ORDER BY ... then listPage(0,1)).
- Check data for unintended duplicates.
Example fix
// before
Task t = taskService.createNativeTaskQuery()
.sql("SELECT * FROM ACT_RU_TASK WHERE NAME_ = #{name}")
.parameter("name", name).singleResult(); // may match many
// after
List<Task> ts = taskService.createNativeTaskQuery()
.sql("SELECT * FROM ACT_RU_TASK WHERE NAME_ = #{name} ORDER BY CREATE_TIME_ DESC")
.parameter("name", name).listPage(0, 1);
Task t = ts.isEmpty() ? null : ts.get(0); Defensive patterns
Strategy: try-catch
Validate before calling
// verify uniqueness first Long n = nativeQuery.sql(sameSql).count(); // or run list() and check size <= 1
Try / catch
try { return query.singleResult(); } catch (ActivitiException e) { if (e.getMessage().contains("results instead of max 1")) { return query.listPage(0,1).stream().findFirst().orElse(null); } throw e; } Prevention
- Only call singleResult() on queries filtering by primary/unique keys
- Prefer list() plus size checks in application code
- Add DB constraints/unique indexes on custom tables queried natively
When it happens
Trigger: Calling nativeQuery().singleResult() where the native SQL matches multiple rows (e.g. missing unique filter like id = ? or an unprescribed where clause).
Common situations: Native queries written against tables with several matching records (multiple historic instances, versions, or active jobs); duplicated data in custom tables; missing LIMIT because singleResult was assumed to limit the query (it does not limit semantically — it fetches all and checks).
Related errors
- Query return " + results.size() + " results instead of max 1
- Query return " + results.size() + " results instead of max 1
- Query return " + results.size() + " results instead of max 1
- activatedBefore is null
- Activiti database problem
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/6391c86088eb2646.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/AbstractNativeQuery.java:168
}
}
public abstract long executeCount(CommandContext commandContext, Map<String, Object> parameterMap);
/**
* Executes the actual query to retrieve the list of results.
*
* @param maxResults
* @param firstResult
*/
public abstract List<U> executeList(CommandContext commandContext, Map<String, Object> parameterMap, int firstResult, int maxResults);
public U executeSingleResult(CommandContext commandContext) {
List<U> results = executeList(commandContext, getParameterMap(), 0, Integer.MAX_VALUE);
if (results.size() == 1) {
return results.get(0);
} else if (results.size() > 1) {
throw new ActivitiException("Query return " + results.size() + " results instead of max 1");
}
return null;
}
private Map<String, Object> getParameterMap() {
HashMap<String, Object> parameterMap = new HashMap<>();
parameterMap.put("sql", sqlStatement);
parameterMap.putAll(parameters);
return parameterMap;
}
public Map<String, Object> getParameters() {
return parameters;
}
}
View on GitHub (pinned to d6d39ce1c6)