Skip to content

@amplitude/analytics-core incompatible with React Native Hermes engine — getGlobalScope, btoa/atob, and document.cookie errors #1549

@inaam-ullah

Description

@inaam-ullah

@amplitude/analytics-core — React Native Hermes Compatibility Issues

Environment

Package Version
react-native 0.73.6
JS Engine Hermes
@amplitude/analytics-core 2.39.0
@amplitude/analytics-react-native 1.4.11
@amplitude/plugin-session-replay-react-native 0.4.2

Problems & Root Causes

1. TypeError: getGlobalScope is not a function (it is undefined)

observers/network.js imports from ".." (the package root). In React Native, Metro resolves this to the ESM version (lib/esm/index.js) instead of CJS, causing getGlobalScope to arrive as undefined and crashing the app on startup.

// network.js - problematic
var __1 = require("..");  // resolves to ESM in React Native — getGlobalScope is undefined

2. Property 'btoa' doesn't exist

storage/cookie.js uses btoa/atob which are browser-only APIs. The Hermes JS engine does not provide these globals, causing a crash whenever Amplitude attempts to store data in cookies.

// cookie.js - problematic
str = "".concat(key, "=").concat(btoa(encodeURIComponent(JSON.stringify(value))));

3. Cannot set property 'cookie' of undefined

storage/cookie.js unconditionally accesses globalScope.document.cookie, but document does not exist in React Native. The existing guard only checks if (globalScope) but not whether globalScope.document exists.

// cookie.js - problematic
if (globalScope) {
  globalScope.document.cookie = str; // crashes — document is undefined in React Native
}

Fix (via patch-package)

diff --git a/node_modules/@amplitude/analytics-core/lib/cjs/observers/network.js b/node_modules/@amplitude/analytics-core/lib/cjs/observers/network.js
index f3c3793..7ea8624 100644
--- a/node_modules/@amplitude/analytics-core/lib/cjs/observers/network.js
+++ b/node_modules/@amplitude/analytics-core/lib/cjs/observers/network.js
@@ -2,7 +2,7 @@
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.networkObserver = exports.NetworkObserver = exports.NetworkEventCallback = void 0;
 var tslib_1 = require("tslib");
-var __1 = require("..");
+var __1 = require("../global-scope");
 var uuid_1 = require("../utils/uuid");
 var network_request_event_1 = require("../network-request-event");

diff --git a/node_modules/@amplitude/analytics-core/lib/cjs/storage/cookie.js b/node_modules/@amplitude/analytics-core/lib/cjs/storage/cookie.js
index 11ab90d..1599efd 100644
--- a/node_modules/@amplitude/analytics-core/lib/cjs/storage/cookie.js
+++ b/node_modules/@amplitude/analytics-core/lib/cjs/storage/cookie.js
@@ -2,6 +2,7 @@
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.isDomainEqual = exports.decodeCookieValue = exports.CookieStorage = void 0;
 var tslib_1 = require("tslib");
+var Buffer = require("buffer").Buffer;
 var global_scope_1 = require("../global-scope");
 var uuid_1 = require("../utils/uuid");
@@ -170,7 +171,7 @@ var CookieStorage = /** @class */ (function () {
-                    str = "".concat(key, "=").concat(btoa(encodeURIComponent(JSON.stringify(value))));
+                    str = "".concat(key, "=").concat(Buffer.from(encodeURIComponent(JSON.stringify(value))).toString('base64'));
@@ -186,7 +186,7 @@
-                    if (globalScope) {
+                    if (globalScope && globalScope.document) {
                         globalScope.document.cookie = str;
@@ -222,7 +222,7 @@
-        return decodeURIComponent(atob(value));
+        return decodeURIComponent(Buffer.from(value, 'base64').toString('binary'));
@@ -232,7 +232,7 @@
-        return decodeURIComponent(atob(decodeURIComponent(value)));
+        return decodeURIComponent(Buffer.from(decodeURIComponent(value), 'base64').toString('binary'));

Suggested Fix for the Amplitude Team

  1. observers/network.js — Import directly from "../global-scope" instead of ".." to avoid ESM/CJS resolution issues in Metro bundler.
  2. storage/cookie.js — Replace btoa/atob with Buffer.from() which is available in React Native via the buffer package, or add a fallback for non-browser environments.
  3. storage/cookie.js — Add a globalScope.document guard before accessing document.cookie to prevent crashes in environments without a DOM.

This issue was created with the help of patch-package.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions