Describe the bug
The 6.x Evaluator contains a bug in its segment matching logic.
When a segment is checked against a context in segmentMatchesContext, the segment key is added to a segment stack for cycle detection purposes. If no segment rule matches the context, the segment key is popped off the segment stack, and false is returned. If, however, a segment rule matches the context, true is returned without popping the segment key off the segment stack.
Should a rule not match despite containing a matching segment clause, and the same segment appear in a subsequent rule, the segment match logic will throw EvaluationException the second time it is run on the same segment.
https://github.com/launchdarkly/java-server-sdk/blob/6.0.4/src/main/java/com/launchdarkly/sdk/server/Evaluator.java#L525-L533
state.segmentStack.add(segment.getKey());
int nRules = rules.size();
for (int i = 0; i < nRules; i++) {
SegmentRule rule = rules.get(i);
if (segmentRuleMatchesContext(rule, context, state, segment.getKey(), segment.getSalt())) {
return true; // Returns true without popping the segment key
}
}
state.segmentStack.remove(state.segmentStack.size() - 1);
To reproduce
- Create a segment
Test in LaunchDarkly, and add your user to it
- Create a boolean feature flag with targeting on, and a default variation of
false
- Add a rule: If user is not in segment
Test, serve false
- Add a rule: If user is in segment
Test, serve true
- Evaluate the flag using your user as context
Expected behavior
Flag evaluation should not throw just because the same segment is used in multiple rules a single flag.
SDK version
6.0.1