You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Workflows: don't throw at runtime when a role condition references a missing role - #54779
A workflow with a has-role(...) condition throws WorkflowInvalidStateException: workflowConditionRoleNotFound at runtime when the referenced role is deleted (or otherwise does not exist anymore). The scheduled runner catches and only logs the error, so the workflow silently stops working for the whole realm. The issue also mentions is-member-of behaves the same way.
Root cause
RoleWorkflowConditionProvider.validate() was called at the start of both runtime paths, toPredicate() and evaluate(), even though both methods already handle a missing role correctly (cb.disjunction() for the query predicate, role != null for in-memory evaluation). validate() throws WorkflowInvalidStateException when the role is missing, so the pre-existing, correct handling of a missing role was never reached.
Fix
Removed the validate() calls from the runtime paths (toPredicate() / evaluate()) of:
RoleWorkflowConditionProvider (has-role, the main fix for this issue)
GroupMembershipWorkflowConditionProvider (is-member-of, reported in the issue as also broken)
IdentityProviderWorkflowConditionProvider (has-idp-link, same pattern in evaluate())
The validate() methods themselves are kept as part of the WorkflowConditionProvider interface. Note that workflow create/update validation (WorkflowValidator.validateWorkflow) does not currently call provider validate() — it only checks that the referenced condition provider factories exist — so workflow create/update behavior is unchanged by this PR.
With this change, a condition that references a deleted entity no longer breaks the workflow at runtime: the condition simply matches no resources.
Tests
Added integration tests covering both runtime paths with a missing role/group (workflow creation, resource resolution through activateForAllEligibleResources → toPredicate, and activation through activate → evaluate):
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The missing-role and missing-group tests can pass despite evaluation exceptions because activation catches and logs them, so both need direct assertions that evaluate() returns false.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The identity-provider condition can incorrectly match users linked to a nonexistent provider and execute workflows because it does not check whether the provider exists.
Removing validate() alone does not make a missing identity provider return false: UserResource.addFederatedIdentity() permits links to unknown aliases, and getFederatedIdentitiesStream() returns those links without checking provider existence. Such users can now match and execute the workflow despite the missing provider; return false when getByAlias(expectedAlias) is null.
activate() catches condition-evaluation exceptions in DefaultWorkflowProvider.processEvent(), so the empty-state assertion also passes if the missing-group condition still throws. Assert directly that evaluate() returns false outside that catch boundary to regression-test the in-memory fix.
Review effort: Balanced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #54759
Problem
A workflow with a
has-role(...)condition throwsWorkflowInvalidStateException: workflowConditionRoleNotFoundat runtime when the referenced role is deleted (or otherwise does not exist anymore). The scheduled runner catches and only logs the error, so the workflow silently stops working for the whole realm. The issue also mentionsis-member-ofbehaves the same way.Root cause
RoleWorkflowConditionProvider.validate()was called at the start of both runtime paths,toPredicate()andevaluate(), even though both methods already handle a missing role correctly (cb.disjunction()for the query predicate,role != nullfor in-memory evaluation).validate()throwsWorkflowInvalidStateExceptionwhen the role is missing, so the pre-existing, correct handling of a missing role was never reached.Fix
Removed the
validate()calls from the runtime paths (toPredicate()/evaluate()) of:RoleWorkflowConditionProvider(has-role, the main fix for this issue)GroupMembershipWorkflowConditionProvider(is-member-of, reported in the issue as also broken)IdentityProviderWorkflowConditionProvider(has-idp-link, same pattern inevaluate())The
validate()methods themselves are kept as part of theWorkflowConditionProviderinterface. Note that workflow create/update validation (WorkflowValidator.validateWorkflow) does not currently call providervalidate()— it only checks that the referenced condition provider factories exist — so workflow create/update behavior is unchanged by this PR.With this change, a condition that references a deleted entity no longer breaks the workflow at runtime: the condition simply matches no resources.
Tests
Added integration tests covering both runtime paths with a missing role/group (workflow creation, resource resolution through
activateForAllEligibleResources→toPredicate, and activation throughactivate→evaluate):RoleWorkflowConditionTest#testConditionForNonExistingRoleGroupWorkflowConditionTest#testConditionForNonExistingGroupBoth fail with
WorkflowInvalidStateExceptionbefore the fix and pass after it.Verification
mvn compile -pl model/jpapasses.