Skip to content

fix: unwrap TraitConfig values in local evaluation before segment matching#252

Merged
khvn26 merged 2 commits intomainfrom
fix/trait-config-local-evaluation
Mar 16, 2026
Merged

fix: unwrap TraitConfig values in local evaluation before segment matching#252
khvn26 merged 2 commits intomainfrom
fix/trait-config-local-evaluation

Conversation

@talissoncosta
Copy link
Contributor

@talissoncosta talissoncosta commented Mar 16, 2026

Summary

  • Fixes a bug where segment overrides are not applied during local evaluation when traits are passed using the TraitConfig format (e.g. { value: 'gold', transient: true })
  • The TraitConfig object was passed directly to the evaluation engine without extracting the .value, causing segment condition comparisons like 'gold' == { value: 'gold', transient: true } to always return false
  • The remote evaluation path already handled this correctly via isTraitConfig() — this fix applies the same unwrapping in getIdentityFlagsFromDocument and getIdentitySegments

Root Cause

In sdk/index.ts, both getIdentityFlagsFromDocument (line 475) and getIdentitySegments (line 278) mapped traits as:

Object.keys(traits).map(key => ({ key, value: traits[key] }))

This passed the entire TraitConfig object { value: 'gold', transient: true } as the trait value, instead of just 'gold'.

Fix

Use the existing isTraitConfig() helper to unwrap values before passing to the engine:

value: isTraitConfig(traits[key]) ? traits[key].value : traits[key]

Validated Against Real Staging Environment

SDK State Plain traits result TraitConfig result Status
Fix reverted "segment override" "default" (wrong) MISMATCH — bug confirmed
Fix applied "segment override" "segment override" MATCH — bug fixed

Test plan

  • Added test: getIdentityFlags with plain traits matches segment (baseline)
  • Added test: getIdentityFlags with TraitConfig format matches segment
  • Added test: getIdentityFlags with mixed trait formats matches segment
  • Added test: getIdentitySegments with TraitConfig format matches segment
  • All 179 existing tests pass
  • Reproduced and validated against real Flagsmith staging environment

Fixes #253

🤖 Generated with Claude Code

@talissoncosta talissoncosta requested a review from a team as a code owner March 16, 2026 17:26
@talissoncosta talissoncosta requested review from khvn26 and removed request for a team March 16, 2026 17:26
talissoncosta and others added 2 commits March 16, 2026 14:32
Add tests verifying that segment matching works correctly when traits
are passed using the TraitConfig format ({ value, transient }) in
local evaluation mode. These tests expose a bug where TraitConfig
objects are passed to the engine without unwrapping the actual value,
causing segment rules to never match.

Tests added:
- getIdentityFlags with plain traits matches segment (baseline)
- getIdentityFlags with TraitConfig format matches segment
- getIdentityFlags with mixed trait formats matches segment
- getIdentitySegments with TraitConfig format matches segment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ching

TraitConfig objects ({ value, transient }) were passed directly to the
evaluation engine without extracting the actual value. This caused
segment condition comparisons to fail (e.g. 'cedars' == { value: 'cedars',
transient: true } → false), so segment overrides were never applied.

The remote evaluation path already handled this correctly via
isTraitConfig() in generateIdentitiesData. This fix applies the same
unwrapping in getIdentityFlagsFromDocument and getIdentitySegments.

Fixes #238

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@khvn26 khvn26 merged commit 4e37994 into main Mar 16, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TraitConfig values not unwrapped during local evaluation, causing segment overrides to fail

2 participants