Repository navigation
fix: return the default value for an invalid context without creating analytics events - #204
Merged
Merged
Conversation
… analytics events Evaluating a flag with an invalid context (a missing key, or a kind or key that is not a binary) only validated the context once the flag had been found. When the flag was unknown or deleted, or when evaluating it raised, the evaluator still created a feature event carrying the invalid context, and the event server crashed when it derived the context's canonical key for index-event deduplication. Each such evaluation lost the buffered events and the open summary; a burst of them exceeded the event supervisor's restart intensity and restarted the instance supervisor, which came back without its feature store and update processor while initialized/1 still returned true. With the synchronous add_event the caller at least saw the exit; with the asynchronous pipeline in #202 the failure is silent. Every place that creates an event now validates the context first. The unknown-flag, deleted-flag and exception results go through one helper that returns the default value with {error, user_not_specified}, logs a warning and records no event when the context is invalid, as the other server-side SDKs do; the known-flag path keeps its existing check and now logs the same warning. A valid context is therefore validated exactly once per evaluation and the known-flag path costs the same as before. is_valid/2 is wrapped so a term that is not a context at all counts as invalid instead of raising.
kinyoklion
force-pushed
the
rlamb/fix-invalid-context-evaluation
branch
from
October 8, 2026 16:56
9c864bc to
5315a2c
Compare
joker23
approved these changes
Oct 8, 2026
kinyoklion
pushed a commit
that referenced
this pull request
Oct 21, 2026
🤖 I have created a release *beep* *boop* --- ## [3.12.1](v3.12.0...v3.12.1) (2026-10-20) ### Bug Fixes * Filter emSign ECC Root CA - G3 out of the bundled certifi store ([#206](#206)) ([6c5980d](6c5980d)) * return the default value for an invalid context without creating analytics events ([#204](#204)) ([0bc26ea](0bc26ea)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Overview** > **Release 3.12.1** bumps the SDK version from **3.12.0** to **3.12.1** in the Release Please manifest, `ldclient.app.src`, and the `VERSION` constant in `ldclient_config`, and adds a **CHANGELOG** entry for 2026-10-20. > > This patch release packages two bug fixes already on `main`: filtering **emSign ECC Root CA - G3** out of the bundled **certifi** trust store when TLS falls back to certifi, and returning flag **defaults for invalid contexts** without emitting analytics events. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f65f80f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Requirements
Related issues
Found while reviewing #202. The fix is independent of that PR and applies to its branch unchanged (the evaluator is not modified there).
Describe the solution you've provided
Evaluating a flag with an invalid context (a missing key, or a kind or key that is not a binary) only validated the context once the flag had been found. When the flag was unknown or deleted, or when evaluating it raised, the evaluator still created a feature event carrying the invalid context, and the event server crashed when it derived the context's canonical key for index-event deduplication.
Each such evaluation lost the buffered events and the open summary. A burst of them exceeded the event supervisor's restart intensity and restarted the instance supervisor, which comes back without its feature store and update processor while
initialized/1still returns true. With the synchronousadd_eventonmainthe caller at least saw the exit; with the asynchronous pipeline in #202 the failure is silent.Every place that creates an event now validates the context first. The unknown-flag, deleted-flag and exception results go through one helper (
unknown_flag_result/4) that returns the default value with{error, user_not_specified}, logs a warning and records no event when the context is invalid, as the other server-side SDKs do. The known-flag path keeps its existing check inflag_for_context_check_valid/5and now logs the same warning. A valid context is validated exactly once per evaluation, so the known-flag path costs the same as before; the unknown-flag path pays oneis_valid/2call (about 130 ns for a single-kind context) on top of the warning it already logs.ldclient_context:is_valid/2is wrapped so a term that is not a context at all counts as invalid instead of raising.Tests:
unknown_flag_with_invalid_context(five invalid shapes against an unknown, a deleted and a known flag),exception_with_invalid_context_sends_no_event(the feature store raising, as it does once the store has been lost; a valid context keeps the existing exception event, an invalid one records nothing) andinvalid_context_does_not_crash_the_event_server(public API; the event server keeps its pid and still delivers afterwards). All three fail onmainwithout the change.Describe alternatives you've considered
Checking the context once at the top of
flag_key_for_context/4is simpler to reason about but validates known flags twice (the per-flag check is still needed byall_flags_state, which calls the lower-level function directly) and changes the result for an invalid context on an offline or not-yet-initialised instance fromclient_not_readytouser_not_specified. Guardingldclient:variation/4andvariation_detail/4the wayidentifyandtrackalready do would cover the public API but not internal callers. Making the event server tolerate a bad context would hide the error from the caller and would have to be done separately onmainand in #202.Additional context
Also reproducible with
ldclient:variation(<<"missing-flag">>, #{kind => <<"org">>, key => 42}, false).Note
Overview
Invalid contexts no longer emit analytics events on unknown-flag, deleted-flag, or evaluation-exception paths—preventing the event server from crashing when it canonicalizes a bad context.
Evaluation now routes those outcomes through
unknown_flag_result/4, which checksis_valid_context/1first. Valid contexts keep prior behavior (including unknown-flag events and warnings forflag_not_found). Invalid contexts use sharedinvalid_context_result/2: default value,{error, user_not_specified}, a warning, and no events—aligned with the known-flag path and other server SDKs.The exception handler in
flag_key_for_context/4uses the same helper instead of always building an unknown-flag event.flag_for_invalid_contextnow logs the same invalid-context warning viainvalid_context_result.Tests cover invalid context shapes against unknown/deleted/known flags, exception + invalid context (no event), and that the event server stays alive through the public API.
Reviewed by Cursor Bugbot for commit 5315a2c. Bugbot is set up for automated code reviews on this repo. Configure here.