Why is my flag evaluation returning an error?
Last updated:
The evaluator picked a variation key the flag no longer defines, which normally means a rule or fallthrough still references a deleted variation. The SDK serves the default value you passed and reports Error, declining to guess which survivor you meant. A variation that exists but holds a null value falls outside this, so the reason string reliably separates a config problem from a data one.
The word covers less ground than you would think, and it has nothing to do with the network or a crashed SDK. Evaluation ran all the way to completion and selected a variation key. The flag does not define it.
The usual cause is a deleted variation that something still references. A flag with three variations gets trimmed to two, a rule further down the list was still serving the third, and that rule now resolves to a key that no longer exists. The SDK will not guess which of the survivors you meant, so it serves the default value you passed at the call site and labels the reason honestly.
Reading it
const detail = client.variationDetail('checkout-experiment', ctx, false);// { value: false, reason: 'Error' }Error is a separate reason from FlagNotFound, which means the flag is absent from the SDK’s snapshot entirely, and from Fallthrough, which means everything worked and no rule matched. Server-side responses use the kebab-case spelling error for the same condition.
A variation that genuinely exists and holds a null value is perfectly valid, so the check does a key lookup. Test the value and you cannot separate an intentional null from a missing variation. Treating that null as a fault would be its own bug.
Finding the stale reference
Open the flag’s targeting configuration and read every serve, including the fallthrough and any rules further down than the one you were looking at. You are looking for a variation key that is no longer in the variations list.
The audit log is faster if the flag has been edited recently, since the variation removal and the rule that outlived it will be adjacent entries.
Preventing it
Removing a variation that a prerequisite depends on is already blocked, which rules out one whole class of this. Rules within the same flag are what need the manual check.
Point every rule at a surviving variation before you delete the old one, in that order. Keep passing a sensible default at each call site too, since your users get that default on the day this happens.
Every reason string the evaluator can emit is listed in the analytics integration guide. For tracing when the variation actually disappeared, the audit log guide is faster than reading the config.
Related questions
Why is my feature flag returning the default value?
Six reasons a Featureflip flag falls back to the default you passed, ordered by how often each one is the real cause, with the check for each.
Why is my feature flag returning the wrong type?
SDKs do not coerce types. Asking for a boolean from a string flag returns the default you passed rather than converting, so code and dashboard disagree.
Why did my targeting rule not match?
Rules run top to bottom and the first match wins, so an earlier rule can shadow the one you are testing. The other usual cause is a missing context attribute.
Still stuck?
The docs cover every SDK, and the free Solo plan is enough to reproduce most of these locally.