Skip to content

fix(react-native): fall back to Platform for $os_name and $os_version - #5294

Merged
turnipdabeets merged 1 commit into
mainfrom
fix/rn-os-name-platform-fallback
Oct 22, 2026
Merged

turnipdabeets merged 1 commit into
mainfrom
fix/rn-os-name-platform-fallback

Conversation

@turnipdabeets

Copy link
Copy Markdown
Contributor

Problem

In a React Native app that installs neither expo-device nor react-native-device-info, every event the JS SDK sends lacks $os_name and $os_version. getAppProperties only reads them from those optional libraries and has no fallback.

Found while testing bare RN 0.79 and 0.76 apps (Release, Android and iOS) for #5271 / #5293. Every JS-sent event from those apps (custom events, $screen, non-fatal $exception) had no OS properties. Fatal $exception events from the same apps did have them, because they go through the native SDK, which adds its own device properties. The Expo example (with expo-device) has them on every event.

Impact:

  • Events from bare apps can't be broken down or filtered by OS.
  • $os_name feeds the default person properties used for flag targeting, so OS-targeted flags never match these users.

The posthog.com install command for bare RN includes react-native-device-info, but nothing says what is lost without it. The SDK's own logs already read the OS from Platform.

Changes

  • When no device library has set $os_name, getAppProperties fills $os_name and $os_version from React Native's Platform:
    • Android: 'Android' and Platform.constants.Release (the user-facing version, not the API level).
    • iOS: Platform.constants.systemName (falls back to 'iOS') and Platform.Version.
    • This matches what posthog-android and posthog-ios report natively.
  • Values from expo-device or react-native-device-info still win when either is installed.
  • Other platforms (web, macOS, Windows) are unchanged.
  • App and device-model properties ($app_version, $app_namespace, $device_manufacturer, …) still need a device-info library. A docs note saying so is worth adding separately.
  • No sdk-spec requires $os_name (sdk-specs lists $os as collected from the host environment). No earlier issues or PRs found.

Test plan

  • New test/native-deps-os.spec.ts (4 cases): 3 fail before the change and all pass after.
  • posthog-react-native vitest suite (1248 tests), build, lint and format pass.
  • Not run on a device yet. The missing properties were observed on device in the bare RN 0.79 / 0.76 apps.

Release info Sub-libraries affected

Libraries affected

  • All of them
  • posthog-js (web)
  • posthog-js-lite (web lite)
  • posthog-node
  • posthog-react-native
  • @posthog/react-native-plugin
  • @posthog/react
  • @posthog/ai
  • @posthog/convex
  • @posthog/next
  • @posthog/nextjs-config
  • @posthog/nuxt
  • @posthog/openfeature-node-provider
  • @posthog/openfeature-web-provider
  • @posthog/rollup-plugin
  • @posthog/webpack-plugin
  • @posthog/types
  • @posthog/browser-common

Checklist

  • Tests for new code
  • Accounted for the impact of any changes across different platforms
  • Accounted for backwards compatibility of any changes (no breaking changes!)
  • Took care not to unnecessarily increase the bundle size

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Claude Code (Claude Opus 5.5) subagent: read the SDK source and test-project events through the PostHog MCP, then wrote the fallback and its test.
  • I confirmed the issue isn't specific to error boundaries: every JS-sent event from the bare apps lacked the properties, so the fix belongs in getAppProperties, not in the boundary.

🤖 Generated with Claude Code

Bare apps without expo-device or react-native-device-info sent JS events without OS properties.
@github-actions

Copy link
Copy Markdown
Contributor

Coherence

2 spec problems · 0 failing chokepoints · 2 spec gaps · 0 guard failures

44 components, 5 bullets (5 invariants, 0 requirements), 2 problems

Spec problems (spec --check)

  • Posthog-js.practice.md:20 practice add an invariant cites 187a5c5, which is no commit in this repository
  • Posthog-js.practice.md:20 practice add an invariant cites 8922ab2, which is no commit in this repository

Chokepoints: none declared.

Spec gaps: 2 entrances with outside or unknown trust and no traced control, and 10 more held by the adoption baseline

  • packages/web/Web.spec.md entrance public api (trust host-app): packages/web
  • packages/webpack-plugin/Webpack-plugin.spec.md entrance webpack plugin (trust build): packages/webpack-plugin

Close one with guard: <chokepoint>, an invariant that names it on its entrances: line, or control: none — <reason>; scaffold control proposes it.

@github-actions

Copy link
Copy Markdown
Contributor

This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the stale label – otherwise this will be closed in another week.

@github-actions github-actions Bot added the stale label Oct 21, 2026
@turnipdabeets
turnipdabeets marked this pull request as ready for review October 21, 2026 21:15
@turnipdabeets
turnipdabeets requested a review from a team as a code owner October 21, 2026 21:15

@marandaneto marandaneto left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The code looks good; no qualifying findings. Verdict: correct.

@turnipdabeets
turnipdabeets added this pull request to the merge queue Oct 22, 2026
Merged via the queue into main with commit ff7aa53 Oct 22, 2026
68 checks passed
@turnipdabeets
turnipdabeets deleted the fix/rn-os-name-platform-fallback branch October 22, 2026 15:01
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.

2 participants