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

  1. Annotate any custom ScopedAssociation subclass with a valid CDI scope, e.g. @ConversationScoped or @RequestScoped.
  2. 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.
  3. 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

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


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)