flowable/flowable-engine · error · FlowableException
No matching parent execution for error code " + errorId + "…
Error message
No matching parent execution for error code " + errorId + " found for " + delegateExecution
What it means
Thrown by ErrorPropagation.executeCatch as a FlowableException when an error being propagated (propagateError) cannot be matched to any parent execution's error boundary event, error start event, or event handler for the given error code. No catch construct exists anywhere in the parent execution hierarchy, so Flowable cannot deliver the error.
Solutions
- Add or fix an error boundary event / error event subprocess whose errorRef matches the thrown error code
- Ensure the boundary event is attached to the correct activity (one that encloses the throwing execution)
- Verify the error code string matches exactly (case, whitespace) between throw site and catch definition
- If the process should end on unmatched errors, catch the BpmnError earlier or add a fallback error event subprocess
Example fix
// before: no catch defined, delegate throws
throw new BpmnError("VALIDATION_FAILED");
// after: add to BPMN on the enclosing service task
<boundaryEvent id="catchValidation" attachedToRef="validateTask">
<errorEventDefinition errorRef="VALIDATION_FAILED"/>
</boundaryEvent> Defensive patterns
Strategy: validation
Validate before calling
// Before throwing, confirm a catch exists for the error code in the deployment
boolean hasCatch = model.getBpmnModel().getMainProcess().getFlowElementsStream()
.anyMatch(fe -> fe instanceof BoundaryEvent
&& ((BoundaryEvent) fe).getEventDefinitions().stream()
.anyMatch(ed -> ed instanceof ErrorEventDefinition
&& code.equals(((ErrorEventDefinition) ed).getErrorRef())));
if (!hasCatch) throw new IllegalStateException("No boundary event catches error code " + code); Try / catch
try { runtimeService.startProcessInstanceByKey(key, vars); }
catch (FlowableException e) {
if (e.getMessage() != null && e.getMessage().startsWith("No matching parent execution for error code")) {
log.error("Uncaught BPMN error: {}", e.getMessage());
} else throw e;
} Prevention
- Keep thrown error codes and errorRef values in a shared constants class
- Ensure every BpmnError throw site is covered by a boundary event or error event subprocess
- Test error paths (happy path only tests will miss this) in CI
When it happens
Trigger: A BpmnError is thrown (BpmnError.throwException / delegateExecution) with an error code, but no error boundary event, error event subprocess, or error start event matching that code exists on any parent execution — the matching lookup returns null and executeCatch throws.
Common situations: Typo or mismatch between the thrown error code and the boundary event's errorRef; missing errorRef attribute on the boundary event; error thrown from a call activity or listener where the catching scope was expected to exist; error code changed in the delegate but not in the model.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Error Code must not be empty.
- Error Code must not be null.
- ${errorCode}
- No matching parent execution for activity
- Activity needed for multi instance cannot bv found
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/84bdc7d414eafedc.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ErrorPropagation.java:264
"ERROR_EVENT " + errorId, false, false, false);
// Event
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
FlowableEventDispatcher eventDispatcher = null;
if (processEngineConfiguration != null) {
eventDispatcher = processEngineConfiguration.getEventDispatcher();
}
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
processEngineConfiguration.getEventDispatcher()
.dispatchEvent(FlowableEventBuilder.createEntityEvent(FlowableEngineEventType.PROCESS_COMPLETED_WITH_ERROR_END_EVENT, processInstanceEntity),
processEngineConfiguration.getEngineCfgKey());
}
}
executeEventHandler(matchingEvent, parentExecution, currentExecution, errorVariableContainer);
} else {
throw new FlowableException("No matching parent execution for error code " + errorId + " found for " + delegateExecution);
}
}
protected static void executeEventHandler(Event event, ExecutionEntity parentExecution, ExecutionEntity currentExecution,
BpmnErrorVariableContainer errorVariableContainer) {
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
FlowableEventDispatcher eventDispatcher = null;
String errorId = errorVariableContainer.getErrorCode();
String errorCode = errorId;
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(parentExecution.getProcessDefinitionId());
if (bpmnModel != null) {
String modelError = bpmnModel.getErrors().get(errorId);
if (modelError != null) {
errorCode = modelError;
errorVariableContainer.setErrorCode(errorCode);
}
}View on GitHub (pinned to d6d39ce1c6)