Skip to content

fix(pre-init): stop processPreloadedItem mutating the shared ready-queue item#1292

Open
darrenli-rokt wants to merge 1 commit into
mParticle:masterfrom
darrenli-rokt:fix/preinit-queue-mutation-crash
Open

fix(pre-init): stop processPreloadedItem mutating the shared ready-queue item#1292
darrenli-rokt wants to merge 1 commit into
mParticle:masterfrom
darrenli-rokt:fix/preinit-queue-mutation-crash

Conversation

@darrenli-rokt

Copy link
Copy Markdown

Problem

processPreloadedItem (src/pre-init-utils.ts) splices the queued item array in place:

const args = readyQueueItem;      // same reference as the item in the ready queue
const method = args.splice(0, 1)[0];

The ready queue can be drained more than once (e.g. a synchronous cache-hit identify re-enters processReadyQueue via parseIdentityResponse before the outer drain resets the queue). On a second pass over an already-consumed item, the array has already been stripped:

  • ["Identity.login", opts][opts]method is an object → method.split('.') throws "e.split is not a function"
  • ["logEvent"][]method is undefined"Cannot read properties of undefined (reading 'split')"

method.split('.') is outside the local try/catch, so the TypeError propagates up through sendIdentityRequest and is reported with code IDENTITY_REQUEST ("Error sending identity request to servers - ...") — even though the identity request itself succeeded. This surfaces as a high volume of misleading IDENTITY_REQUEST client-error reports.

Fix

  • Operate on a copy of the queued item (readyQueueItem.slice()) so a repeat drain cannot corrupt the shared array.
  • Skip malformed entries (empty array / non-string method) instead of throwing an uncaught TypeError.

Existing behaviour is otherwise unchanged (all pre-existing tests pass untouched).

Tests

Full jest suite green. Added regression tests in test/jest/pre-init-utils.spec.ts:

  • the queued item is not mutated after processing (can be drained again)
  • draining the same queue twice does not throw
  • malformed items (empty array, non-string method) are skipped

Follow-up (not in this PR)

This stops the crash and the mislabelled IDENTITY_REQUEST errors. A complementary hardening is to make the ready-queue drain itself re-entrancy-safe (reset the queue before draining) so a queued method is not executed twice under re-entrancy. There is also a separate latent issue at the window.mParticle[args[0]] membership check (it should key off method), left untouched here to keep the diff surgical.

…eue item

processPreloadedItem spliced the queued item array in place. Because the
ready queue can be drained more than once (e.g. a synchronous cache-hit
identify re-enters processReadyQueue before the outer drain resets the
queue), a second pass over an already-consumed item saw a stripped array:
["Identity.login", opts] had become [opts], so `method` was an object (or
`undefined` for a single-element item) and the unguarded `method.split('.')`
threw a TypeError. That TypeError surfaces from within sendIdentityRequest's
try/catch and gets reported with code IDENTITY_REQUEST ("Error sending
identity request to servers - e.split is not a function" / "...reading
'split'"), even though the identity request itself succeeded.

Fix:
- operate on a copy of the queued item so repeat drains cannot corrupt it
- skip malformed entries (empty array / non-string method) instead of
  throwing an uncaught TypeError

Existing behaviour is otherwise unchanged. Adds regression tests: item is
not mutated, the same queue can be drained twice without throwing, and
malformed items are skipped.

Note: this stops the crash and the mislabelled IDENTITY_REQUEST errors; a
complementary follow-up is to make the ready-queue drain itself
re-entrancy-safe (reset before draining) so a method is not run twice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@darrenli-rokt
darrenli-rokt marked this pull request as ready for review July 23, 2026 13:57
@darrenli-rokt
darrenli-rokt requested a review from a team as a code owner July 23, 2026 13:57
@cursor

cursor Bot commented Jul 23, 2026

Copy link
Copy Markdown

PR Summary

Cursor Bugbot is generating a summary for commit 57972d0. Configure here.

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.

1 participant