Skip to content

Conversation

@joker23
Copy link
Contributor

@joker23 joker23 commented Dec 3, 2025

This commit will allow variation calls to use bootstrapped values during the client initialization process.

The bootstrap configuration will only be done once per client instance as we expect this fall back will only be active for a brief amount of time.


Note

Enables pre-initialization flag evaluation by applying bootstrap flags once during identify, with a new shared setBootstrap hook.

  • Browser SDK (packages/sdk/browser/src/BrowserClient.ts)
    • Apply bootstrap during identifyResult: read flags via readFlagsFromBootstrap, call setBootstrap(context, data), with a once-only guard (_bootstrapAttempted) and error logging.
  • Shared SDK Client (packages/shared/sdk-client/src/LDClientImpl.ts)
    • Add protected setBootstrap(pristineContext, newFlags) to set context and initialize flags via FlagManager.setBootstrap.
    • Import ItemDescriptor for bootstrap flag descriptors.

Written by Cursor Bugbot for commit 15e59c7. This will update automatically on new commits. Configure here.

This commit will allow variation calls to use bootstrapped values during the client initialization process.
@joker23 joker23 requested a review from a team as a code owner December 3, 2025 00:21
@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

@launchdarkly/browser size report
This is the brotli compressed size of the ESM build.
Compressed size: 169118 bytes
Compressed size limit: 200000
Uncompressed size: 789399 bytes

@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

@launchdarkly/js-client-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 17726 bytes
Compressed size limit: 20000
Uncompressed size: 90839 bytes

@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 22171 bytes
Compressed size limit: 25000
Uncompressed size: 76527 bytes

@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 25394 bytes
Compressed size limit: 26000
Uncompressed size: 124693 bytes

this._uncheckedContext = pristineContext;
this._checkedContext = Context.fromLDContext(this._uncheckedContext);
this._flagManager.setBootstrap(this._checkedContext, newFlags);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Bootstrap fails silently for contexts without valid keys

The setBootstrap method doesn't validate that the context is valid before calling _flagManager.setBootstrap. When Context.fromLDContext creates an invalid context (e.g., for anonymous contexts without keys like { kind: 'user', anonymous: true }), accessing canonicalKey on this invalid context throws a TypeError because _context is undefined. This error is caught in BrowserClient.identifyResult and logged as "failed to bootstrap data" without explaining the root cause. The bootstrap data is silently lost, and users won't understand why their bootstrap configuration isn't working for anonymous contexts.

Additional Locations (1)

Fix in Cursor Fix in Web

this.logger,
identifyOptionsWithUpdatedDefaults.bootstrap,
);
this.setBootstrap(context, bootstrapData);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Bootstrap uses unprocessed context causing potential key mismatch

The setBootstrap call receives the raw context parameter before super.identifyResult processes it through ensureKey and addAutoEnv. When AutoEnvAttributes are enabled, addAutoEnv converts single-kind contexts to multi-kind by adding ld_application and ld_device kinds, changing the canonical key. This means the _activeContextKey set during early bootstrap differs from the final processed context's canonical key. While this gets corrected when BrowserDataManager._finishIdentifyFromBootstrap is later called with the processed context, flag evaluations during the brief window between these calls may behave unexpectedly.

Fix in Cursor Fix in Web

*/
protected setBootstrap(pristineContext: LDContext, newFlags: { [key: string]: ItemDescriptor }) {
this._uncheckedContext = pristineContext;
this._checkedContext = Context.fromLDContext(this._uncheckedContext);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this will still get ultimately set by the normal code path, which would then handle any normal context processing? Do we need to be setting context information at all? I think in the previous SDK bootstrap would fail to send events before init complete, so this may be better for some cases.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, if nothing else, we need to make sure that the bootstrap data actually gets set even if the context has anonymous contexts without keys.

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.

3 participants