flowable/flowable-engine · error · ActivitiException

destination ' ' not found. (referenced from transition in '…

Error message

destination '${destinationActivityName}' not found.  (referenced from transition in '${sourceActivityId}')

What it means

ActivitiException thrown in buildProcessDefinition when an unresolved transition's destination activity id does not match any activity in the finished process definition. Transitions are created with deferred destinations; resolution happens once, at build time, via processDefinition.findActivity. This indicates a dangling edge in the process graph.

Solutions

  1. Ensure the id passed to startTransition exactly matches an id used in startActivity(...) within the same builder.
  2. Create the destination activity before calling buildProcessDefinition().
  3. Log the source activity id (given in the message) and correct the reference or remove the orphan transition.

Example fix

// before
builder.startTransition("tskApprove"); // activity never declared
// after
builder.startActivity("tskApprove").endActivity();
builder.startActivity("tskStart").startTransition("tskApprove").endActivity(); // now resolves
Defensive patterns

Strategy: validation

Validate before calling

Set<String> declared = new HashSet<>();
// ... collect ids passed to startActivity(...) ...
if (!declared.contains(transitionTargetId)) {
  throw new IllegalArgumentException("transition target '" + transitionTargetId + "' is not a declared activity");
}
builder.buildProcessDefinition();

Try / catch

try {
  PvmProcessDefinition def = builder.buildProcessDefinition();
} catch (ActivitiException e) {
  if (e.getMessage() != null && e.getMessage().contains("not found")) {
    log.error("Dangling transition reference in process model: " + e.getMessage());
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling startTransition(destId, ...) with an id that never matches an activity added via startActivity(id) (or the id was set after buildProcessDefinition), then calling buildProcessDefinition().

Common situations: Typos in target ids, referencing an activity defined in a different scope/process, or building the definition before all activities were declared (order of builder calls).

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/dc38e9732a9ce964. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/ProcessDefinitionBuilder.java:121

    }

    public ProcessDefinitionBuilder behavior(ActivityBehavior activityBehaviour) {
        getActivity().setActivityBehavior(activityBehaviour);
        return this;
    }

    public ProcessDefinitionBuilder property(String name, Object value) {
        processElement.setProperty(name, value);
        return this;
    }

    public PvmProcessDefinition buildProcessDefinition() {
        for (Object[] unresolvedTransition : unresolvedTransitions) {
            TransitionImpl transition = (TransitionImpl) unresolvedTransition[0];
            String destinationActivityName = (String) unresolvedTransition[1];
            ActivityImpl destination = processDefinition.findActivity(destinationActivityName);
            if (destination == null) {
                throw new ActivitiException("destination '" + destinationActivityName + "' not found.  (referenced from transition in '" + transition.getSource().getId() + "')");
            }
            transition.setDestination(destination);
        }
        return processDefinition;
    }

    protected ActivityImpl getActivity() {
        return (ActivityImpl) scopeStack.peek();
    }

    public ProcessDefinitionBuilder scope() {
        getActivity().setScope(true);
        return this;
    }

    public ProcessDefinitionBuilder executionListener(ExecutionListener executionListener) {
        if (transition != null) {
            transition.addExecutionListener(executionListener);

View on GitHub (pinned to d6d39ce1c6)