{"record":{"id":"3c1b8183385475b0","repo":"flowable/flowable-engine","slug":"more-than-one-result-in-decision","errorCode":null,"errorMessage":"more than one result in decision: ","messagePattern":"more than one result in decision: ","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/DmnDecisionServiceImpl.java","lineNumber":95,"sourceCode":"        return decisionResult;\n    }\n\n    @Override\n    public Map<String, Object> executeWithSingleResult(ExecuteDecisionBuilder builder) {\n        ExecuteDecisionContext executeDecisionContext = builder.buildExecuteDecisionContext();\n\n        commandExecutor.execute(new EvaluateDecisionCmd(executeDecisionContext));\n\n        Map<String, Object> singleDecisionResult = null;\n        Map<String, List<Map<String, Object>>> decisionResult = composeEvaluateDecisionResult(executeDecisionContext);\n\n        finalizeDecisionExecutionAudit(executeDecisionContext);\n\n        for (Map.Entry<String, List<Map<String, Object>>> entry : decisionResult.entrySet()) {\n            List<Map<String, Object>> decisionResults = entry.getValue();\n            if (decisionResults != null && !decisionResults.isEmpty()) {\n                if (decisionResults.size() > 1) {\n                    throw new FlowableException(\"more than one result in decision: \" + entry.getKey());\n                }\n                if (singleDecisionResult == null) {\n                    singleDecisionResult = new HashMap<>();\n                }\n                singleDecisionResult.putAll(decisionResults.get(0));\n            }\n        }\n\n        return singleDecisionResult;\n    }\n\n    @Override\n    public Map<String, Object> executeDecisionWithSingleResult(ExecuteDecisionBuilder builder) {\n        ExecuteDecisionContext executeDecisionContext = builder.buildExecuteDecisionContext();\n\n        commandExecutor.execute(new ExecuteDecisionCmd(executeDecisionContext));\n\n        Map<String, Object> singleDecisionResult = null;","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/DmnDecisionServiceImpl.java#L77-L113","documentation":"DmnDecisionServiceImpl.executeWithSingleResult executes a DMN decision and expects the decision result to produce at most one output row per result entry. When the decision result map contains an entry with more than one row, it throws FlowableException(\"more than one result in decision: <decisionKey>\"), because a 'single result' API cannot unambiguously return multiple rows.","triggerScenarios":"Calling executeWithSingleResult against a decision table whose rules match multiple times (overlapping rules, or hit policies like COLLECT/multi-hit that legitimately return several rows) while expecting exactly one output row.","commonSituations":"DMN tables where several rules overlap (e.g. overlapping input ranges) so more than one rule fires; missing exclusive/FIRST hit policy; business rules changed so that what was previously unique now matches twice; using a single-result API with a COLLECT decision table.","solutions":["Make the decision table deterministic: narrow rule conditions so at most one rule can match, or set an appropriate hit policy (e.g. FIRST/unique).","Switch the caller to a multi-result API (executeDecision / collect results) if multiple outputs are legitimate.","Check which decision key the exception names and inspect its overlapping rules; add a distinguishing input condition.","Deduplicate or merge output columns in the model if rows are duplicates of each other."],"exampleFix":"// before\nMap<String, Object> result = ruleService.executeWithSingleResult(config);\n// after\nList<Map<String, Object>> results = ruleService.execute(config); // multi-result API\nif (results.size() > 1) {\n    logger.warn(\"decision matched {} rules; using first\", results.size());\n}\nMap<String, Object> result = results.get(0);","handlingStrategy":"try-catch","validationCode":"// Prefer the multi-result API when the decision table may match several rules:\nList<Map<String, Object>> results = ruleService.execute(config);\nif (results != null && results.size() > 1) {\n    logger.warn(\"decision matched {} rules; using first\", results.size());\n}","typeGuard":null,"tryCatchPattern":"try {\n    result = ruleService.executeWithSingleResult(config);\n} catch (FlowableException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"more than one result in decision\")) {\n        String decisionKey = e.getMessage().substring(e.getMessage().lastIndexOf(':') + 1).trim();\n        // fall back to multi-result execution for this decision\n    } else { throw e; }\n}","preventionTips":["Design decision tables with mutually exclusive rules or a FIRST hit policy","Audit decision tables for overlapping input conditions when changing business rules","Use multi-result APIs whenever COLLECT/multi-hit output is possible","Include the decision key from the exception message to locate the offending table"],"tags":["java","flowable","dmn","decision-table","hit-policy","multiple-results"],"backgroundTag":"unexpected-response-shape","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}