flowable/flowable-engine · error · FlowableException
ScopedAssociation must carry exactly one annotation and it…
Error message
ScopedAssociation must carry exactly one annotation and it must be a @Scope annotation
What it means
DefaultContextAssociationManager.getBroadestActiveContext() walks candidate ScopedAssociation classes ordered by context breadth and requires each to carry a CDI @Scope annotation; it uses that annotation to resolve the active CDI context. If a candidate's first annotation is missing or is not a valid scope type according to BeanManager.isScope(), it throws this FlowableException.
Solutions
- Annotate any custom ScopedAssociation subclass with a valid CDI scope, e.g. @ConversationScoped or @RequestScoped.
- Ensure the scope annotation's @Scope meta-annotation is present and the CDI bean archive (beans.xml with version/bean-discovery-mode) is set up so annotations are visible.
- Align flowable-cdi module version with the rest of your Flowable dependencies.
Example fix
// before
public class CustomScopedAssociation extends ScopedAssociation { }
// after
@ConversationScoped
public class CustomScopedAssociation extends ScopedAssociation { } Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = CustomScopedAssociation.class;
Annotation a = c.getAnnotations().length > 0 ? c.getAnnotations()[0] : null;
boolean valid = a != null && a.annotationType().isAnnotationPresent(javax.enterprise.context.Scope.class);
if (!valid) throw new IllegalStateException("ScopedAssociation needs a CDI @Scope annotation"); Type guard
null
Try / catch
try { businessProcess.getVariable("k"); } catch (FlowableException e) { /* fall back to RuntimeService */ } Prevention
- Always annotate custom ScopedAssociation subclasses with a standard CDI scope
- Keep beans.xml CDI configuration consistent across all modules
- Keep flowable-cdi versions aligned with other Flowable artifacts
When it happens
Trigger: One of the ScopedAssociation classes returned by getAvailableScopedAssociationClasses() has no annotations, or its first annotation is not a CDI scope (e.g. custom association class annotated with a plain qualifier instead of @Conversation/@RequestScoped-style scope).
Common situations: Subclassing ScopedAssociation to add a custom scope but annotating it incorrectly, or classpath mixing of Flowable CDI versions where association classes changed their annotations, or CDI bean archive misconfiguration altering annotation discovery.
Related errors
- Cannot associate , already associated with . Disassociate…
- Cannot associate execution by id: no execution with id '
- Cannot associate with execution: null
- Cannot disassociate execution, no
- Cannot resume task with id '
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2be18c3aac455dff.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cdi/src/main/java/org/flowable/cdi/impl/context/DefaultContextAssociationManager.java:114
}
@ConversationScoped
protected static class ConversationScopedAssociation extends ScopedAssociation implements Serializable {
}
@RequestScoped
protected static class RequestScopedAssociation extends ScopedAssociation implements Serializable {
}
@Inject
private BeanManager beanManager;
protected Class<? extends ScopedAssociation> getBroadestActiveContext() {
for (Class<? extends ScopedAssociation> scopeType : getAvailableScopedAssociationClasses()) {
Annotation scopeAnnotation = scopeType.getAnnotations().length > 0 ? scopeType.getAnnotations()[0] : null;
if (scopeAnnotation == null || !beanManager.isScope(scopeAnnotation.annotationType())) {
throw new FlowableException("ScopedAssociation must carry exactly one annotation and it must be a @Scope annotation");
}
try {
beanManager.getContext(scopeAnnotation.annotationType());
return scopeType;
} catch (ContextNotActiveException e) {
LOGGER.trace("Context {} not active.", scopeAnnotation.annotationType());
}
}
throw new FlowableException("Could not determine an active context to associate the current process instance / task instance with.");
}
/**
* Override to add different / additional contexts.
*
* @return a list of {@link Scope}-types, which are used in the given order to resolve the broadest active context (@link #getBroadestActiveContext()})
*/
protected List<Class<? extends ScopedAssociation>> getAvailableScopedAssociationClasses() {
ArrayList<Class<? extends ScopedAssociation>> scopeTypes = new ArrayList<>();
View on GitHub (pinned to d6d39ce1c6)