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
AbstractQuery.executeSingleResult() backs typedQuery.singleResult(). It runs executeList without paging and throws ActivitiException "Query return N results instead of max 1" when more than one row matches. Unlike SQL, the singleResult() contract does not silently take the first row — multiple matches are an error.
Solutions
- Add unique criteria (processInstanceId, taskId, executionId, processDefinitionId) before singleResult().
- Use .list() and inspect size, or listPage(0,1) plus ORDER BY when multiple matches are valid.
- Use latest().singleResult() variants (e.g. processDefinitionQuery.latestVersion()) where the API supports it.
- Deduplicate data or narrow historic query time range.
Example fix
// before
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("order").singleResult(); // multiple versions match
// after
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("order").latestVersion().singleResult(); Defensive patterns
Strategy: try-catch
Validate before calling
if (query.count() > 1) { /* narrow criteria or use list */ } Try / catch
try { return query.singleResult(); } catch (ActivitiException e) { if (e.getMessage().contains("results instead of max 1")) { return query.listPage(0,1).get(0); } throw e; } Prevention
- Filter by unique ids (processInstanceId, taskId) before singleResult()
- Use latestVersion()/latest() where supported
- Audit queries keyed by business attributes for multi-match risk
When it happens
Trigger: Calling e.g. taskQuery.processDefinitionKey(key).singleResult() where the criteria match several tasks/instances/executions/variables.
Common situations: Queries keyed by non-unique attributes (process definition key instead of id, business key with multiple running instances, variable value shared by many rows); historical queries over long time ranges; deployments producing duplicate definitions.
Related errors
- Query return " + results.size() + " results instead of max 1
- Query return " + results.size() + " results instead of max 1
- activatedBefore is null
- Activiti database problem
- activity tenant id is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/843da0602b69c379.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/AbstractQuery.java:194
}
}
public abstract long executeCount(CommandContext commandContext);
/**
* Executes the actual query to retrieve the list of results.
*
* @param page
* used if the results must be paged. If null, no paging will be applied.
*/
public abstract List<U> executeList(CommandContext commandContext, Page page);
public U executeSingleResult(CommandContext commandContext) {
List<U> results = executeList(commandContext, null);
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;
}
protected void addOrder(String column, String sortOrder, NullHandlingOnOrder nullHandlingOnOrder) {
if (orderBy == null) {
orderBy = "";
} else {
orderBy = orderBy + ", ";
}
String defaultOrderByClause = column + " " + sortOrder;
if (nullHandlingOnOrder != null) {
if (nullHandlingOnOrder == NullHandlingOnOrder.NULLS_FIRST) {
View on GitHub (pinned to d6d39ce1c6)