react-google-maps-api icon indicating copy to clipboard operation
react-google-maps-api copied to clipboard

IntersectionObserver.observe(undefined) crash when using GoogleMap with floating-ui overlays

Open Tibougzing opened this issue 1 week ago • 0 comments

Environment

  • @react-google-maps/api version: latest (^3.x or ^2.x)
  • React version: 18.x
  • Browser: Chrome 142
  • Build tool: Vite
  • Overlay library: floating-ui / Radix (for tooltips/popovers around Google Map)

Description

When integrating @react-google-maps/api with floating-ui / Radix-based overlays in the same component tree, a runtime error occurs:

Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'

This error is triggered during the mount of the GoogleMap component, specifically when the positioning logic (Popper/Radix/floating-ui) attempts to observe an element for layout calculations, but passes undefined instead of a valid DOM Element to IntersectionObserver.observe().

Root Cause

The error originates from the intersection observer logic used by floating-ui / Radix for positioning calculations. During GoogleMap initialization, a race condition or timing issue causes the observer to be called with a null or undefined target, instead of a valid Element reference.

Stack Trace (Abbreviated)

IntersectionObserver.observe called with invalid target: undefined
  at proto.observe (main.tsx:40)
  at y (main.js:253)
  at _.xr (main.js:253)
  at (anonymous) (@react-google-maps_api.js:390)
  at componentDidMount (@react-google-maps_api.js:410)
  at commitLayoutEffectOnFiber (chunk-RPCDYKBN.js:17030)

The error occurs during the componentDidMount hook of the GoogleMap component, originating from floating-ui's positioning update logic.

Console Logs

IntersectionObserver error:

IntersectionObserver.observe called with invalid target:  undefined

Google Maps load status:

[Telemetry] MapLoadReport {ts: 1764436519966, key: 'FAKE_KEY_FOR_DEV', status: 'error', message: 'google.maps.Map not a function or partial load'}

This suggests that the Google Maps library may be partially loaded or not fully initialized when the overlay positioning logic tries to observe elements, causing the race condition.

Steps to Reproduce

  1. Create a React component using @react-google-maps/api with GoogleMap
  2. Wrap the GoogleMap in a floating-ui/Radix-based overlay container (e.g., Popover, Tooltip, or custom Popper)
  3. Mount the component in development mode
  4. Observe the browser console: Failed to execute 'observe' on 'IntersectionObserver'... error appears

Expected Behavior

  • GoogleMap should mount without errors
  • The overlay positioning system should gracefully handle cases where observer targets are not yet available
  • No console errors about invalid IntersectionObserver targets

Actual Behavior

  • Error: "Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'"
  • The error is thrown but doesn't currently crash the page (depending on error boundary setup)
  • However, it indicates a bug that could cause issues in production

Suggested Fix

The issue likely needs a fix in how the library handles observer targets during component lifecycle. Proposed solutions:

  1. In @react-google-maps/api (if applicable):

    • Add a guard check before calling IntersectionObserver methods
    • Verify that target elements exist and are valid DOM elements
    • Defer observer setup until all elements are mounted
  2. In floating-ui / Radix (if the bug originates there):

    • Add validation: if (!target || !(target instanceof Element)) return; before calling observe()
    • Handle race conditions where refs may not be attached yet during layout calculations

Workaround

A defensive patch can be applied to IntersectionObserver globally (for dev/debugging):

// Patch IntersectionObserver.prototype.observe to skip invalid targets
const originalObserve = IntersectionObserver.prototype.observe;
IntersectionObserver.prototype.observe = function(target) {
  if (!target || !(target instanceof Element)) {
    console.warn('[Telemetry] IntersectionObserver.observe called with invalid target:', target);
    console.trace();
    return; // Skip invalid targets gracefully
  }
  return originalObserve.call(this, target);
};

This patch protects against the error but masks the root cause—the actual libraries should fix their validation.

Related Issues / PRs

  • Likely related to floating-ui or Radix's integration with IntersectionObserver
  • May be a known race condition when maps load asynchronously

Additional Context

  • This issue was detected in a production-like environment with potential partial library loads (adblock, CSP issues, etc.)
  • A telemetry system was implemented to capture these observe() calls for debugging
  • The error is reproducible in Vite dev environment and potentially in production builds

Tibougzing avatar Nov 29 '25 17:11 Tibougzing