Skip to content

fix: Create the JS client before the native SDK finishes starting - #1469

Open
lucas-zimerman wants to merge 5 commits into
mainfrom
lz/feat/cache-errors
Open

lucas-zimerman wants to merge 5 commits into
mainfrom
lz/feat/cache-errors

Conversation

@lucas-zimerman

Copy link
Copy Markdown
Collaborator

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

sdkInit used to start the native SDK first and only call the sibling SDK's init once NATIVE.initNativeSdk() resolved. That resolve comes back over the Capacitor bridge as a new task, so the framework bootstrap ran before any JS client existed and everything captured in that window was dropped.

This follows the @sentry/react-native layout (ReactNativeClient.init() → _initNativeSdk()):

  • sdkInit now calls originalInit synchronously and starts the native SDK in the background.
  • When native init settles it calls the new onReady({ didCallNativeInit }) option and emits afterInit on the client.
  • NATIVE.nativeReady holds the pending native init. The native transport waits for it before sending, so events captured during bootstrap are queued instead of dropped. If native failed or is disabled, the transport falls back to the fetch transport (it no longer re-runs originalInit with restored options).
  • The native log listener is registered before initNativeSdk, so logs emitted during native init are not missed.
  • iOS: fetchNativeDeviceContexts / fetchNativeLogAttributes resolved inside the SentrySDK.configureScope callback, which never runs when the native SDK is not started, so the promise never settled and the JS event pipeline stalled. They now reject (Native SDK is not started), like React Native, which resolves outside the callback.

💡 Motivation and Context

Fixes #1463

Errors during app bootstrap (including the framework failing to bootstrap and errors reaching Angular's ErrorHandler) were silently dropped with No client configured on scope. This was a regression compared to calling @sentry/angular's init directly.

💚 How did you test it?

  • Unit tests: updated test/client.test.ts (client created before native resolves, onReady, listener order, failure path) and added readiness/fallback tests in test/transports/native.test.ts. tsc -p tsconfig.build.json, eslint and the full jest suite pass.
  • Android emulator (example/ionic-angular-v8): a captureMessage right after Sentry.init is dropped on main and captured and delivered with this change.
  • iOS simulator (iPhone 17, same app): same result. On main the message is dropped. With this change it passes beforeSend and the envelope is written and sent by the native SDK.
  • iOS with native init forced to fail: before the Swift change, neither an early nor a late (4s) message reached beforeSend. After it, both do and the envelope is POSTed to ingest through the fetch transport.

Not tested: a real native-side start failure (the failure was forced in JS), a real bootstrap crash on iOS, and the Vue example.

📝 Checklist

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec
  • No breaking changes

🔮 Next steps

  • Document the new onReady option.
  • Decide whether wrapper methods other than the transport (scope sync, device context fetch) should also wait for nativeReady; they currently rely on the bridge handling calls in order, as React Native does.

lucas-zimerman and others added 3 commits November 5, 2026 20:43
Mirror @sentry/react-native: sdkInit calls the sibling init synchronously and
starts the native SDK in the background. The native transport waits for native
init and falls back to the fetch transport if it failed, so errors captured
during app bootstrap are no longer dropped. Adds an onReady option and registers
the native log listener before native init.

Fixes #1463

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The core client's typed emit has no afterInit hook, so the call failed
tsc -p tsconfig.build.json.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… is not started

SentrySDK.configureScope only runs its callback when the SDK is started. The
promise was resolved inside the callback, so it never settled when native init
failed and the JS event pipeline stalled. Reject instead, like React Native
which resolves outside the callback.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@lucas-zimerman
lucas-zimerman requested a review from a team as a code owner November 5, 2026 22:11
@lucas-zimerman
lucas-zimerman requested review from alwx and antonis and removed request for a team and alwx November 5, 2026 22:11
Comment thread CHANGELOG.md Resolved

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 03ce6cc. Configure here.

Comment thread src/client.ts Resolved
Comment thread src/client.ts Resolved
lucas-zimerman and others added 2 commits November 5, 2026 22:17
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…Init

The JS client is now created before the native SDK finishes starting, so
fetchNativeDeviceContexts/LogAttributes/Release/SdkInfo could reach native
before SentrySDK.start ran on iOS. They now wait for NATIVE.nativeReady and
reject without calling native when it failed.

An onReady callback that throws no longer skips the afterInit event.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Errors during app bootstrap are dropped: JS client is only created after the native SDK starts

1 participant