Skip to content

[Bug]: iOS 26: SIGTRAP in RNMBXImages.addImages (placeholderImage force unwrap) #4260

Description

@angelolencina

Mapbox Version

11.18.3

React Native Version

0.85.3

Platform

iOS

@rnmapbox/maps version

10.3.1

Standalone component to reproduce

import React from 'react';
import {
  MapView,
  ShapeSource,
  SymbolLayer,
  Images,
  Camera,
} from '@rnmapbox/maps';

const aPoint = {
  type: 'Feature',
  geometry: {
    type: 'Point',
    coordinates: [-74.00597, 40.71427],
  },
  properties: {icon: 'marker'},
};

class BugReportExample extends React.Component {
  render() {
    return (
      <MapView style={{flex: 1}}>
        <Camera centerCoordinate={[-74.00597, 40.71427]} zoomLevel={14} />
        <Images images={{marker: 'https://example.com/marker.png'}} />
        <ShapeSource id="idPointSource" shape={aPoint}>
          <SymbolLayer id="idPointLayer" style={{iconImage: ['get', 'icon']}} />
        </ShapeSource>
      </MapView>
    );
  }
}

Observed behavior and steps to reproduce

Environment

  • @rnmapbox/maps 10.3.1 (checked 10.3.2, same code there)
  • react-native 0.85.3, new architecture
  • iOS 26.5, iPhone14,7 (real device)

We started getting hard crashes in production once users updated to iOS 26. It's a SIGTRAP on the main thread when the style loads and images get added to the map:

0 RNMBXImages.addImages(style:images:oldImages:)
1 RNMBXImages.addImages(style:images:oldImages:)
2 RNMBXImages.addToMap(_:style:)
3 closure #1 (MapView) in RNMBXMapView.addToMap(UIView)
...
13 @objc RNMBXMapView.didSetProps([String])
14 -[RNMBXMapViewComponentView updateProps:oldProps:]

Standalone code example

Nothing special needed — any MapView with an n iOS 26 as soon as the style loads andaddImages runs. Same build works fine on iOS 17/18 devices.

import React from 'react';
import Mapbox from '@rnmapbox/maps';

Mapbox.setAccessToken('pk.xxx');

export default function App() {
  return (
    <Mapbox.MapView style={{flex: 1}}>
      <Mapbox.Camera zoomLevel={14} centerCoordinate={[8.54, 47.37]} />
      <Mapbox.Images images={{marker: 'https://example.com/marker.png'}} />
      <Mapbox.ShapeSource
        id="items"
        shape={{
          type: 'FeatureCollection',
          features: [
            {
              type: 'Feature',
              geometry: {type: 'Point', coordinates: [8.54, 47.37]},
              properties: {icon: 'marker'},
            },
          ],
        }}>
        <Mapbox.SymbolLayer id="items-symbols" style={{iconImage: ['get', 'icon']}} />
      </Mapbox.ShapeSource>
    </Mapbox.MapView>
  );
}

The trap is the force unwrap in placeholderImage (RNMBXImages.swift):

lazy var placeholderImage : UIImage = {
  UIGraphicsBeginImageContextWithOptions(CGSialse, 0.0)
  let result = UIGraphicsGetImageFromCurrentImageContext()!
  UIGraphicsEndImageContext()
  return result
}()

UIGraphicsBeginImageContext* has been deprecated since iOS 17, and on iOS 26 the context creation fails, so UIGraphicsGetImageFromCurrentImageContext() returns nil and the ! traps. In practice every user on iOS 26 crashes
on any screen that renders a map with Images.

Switching to UIGraphicsImageRenderer fixes it

lazy var placeholderImage : UIImage = {
  return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { _ in }
}()

takeSnap in RNMBXMapView.swift has the same I patched that one too.

This is the patch we're shipping via patch-pa

diff --git a/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXImages.swift b/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXImages.swift
index b89393d..0072a24 100644
--- a/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXImages.swift
+++ b/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXImages.swift
@@ -267,10 +267,7 @@ open class RNMBXImages : UIView, RNMBXMapComponent {
   }

   lazy var placeholderImage : UIImage = {
-    UIGraphicsBeginImageContextWithOptions(C, false, 0.0)
-    let result = UIGraphicsGetImageFromCurrentImageContext()!
-    UIGraphicsEndImageContext()
-    return result
+    return UIGraphicsImageRenderer(size: CGSimage { _ in }
   }()
 }

diff --git a/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXMapView.swift b/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXMapView.swift
index 62861b5..dfee057 100644
--- a/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXMapView.swift
+++ b/node_modules/@rnmapbox/maps/ios/RNMBX/RNMBXMapView.swift
@@ -1506,13 +1506,13 @@ extension RNMBXMapVie
   @objc public func takeSnap(
     writeToDisk:Bool) -> URL
   {
-    UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0);
-
-    self.drawHierarchy(in: self.bounds, afte
-    let snapshot = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
+    let format = UIGraphicsImageRendererFormat()
+    format.opaque = true
+    let snapshot = UIGraphicsImageRenderer(b: format).image { _ in
+      self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
+    }

-    return writeToDisk ? RNMBImageUtils.createTempFile(snapshot!) :  RNMBImageUtils.createBase64(snapshot!)
+    return writeToDisk ? RNMBImageUtils.createTempFile(snapshot) :  RNMBImageUtils.createBase64(snapshot)
   }
 }

Expected behavior

No response

Notes / preliminary analysis

No response

Additional links and references

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🪲Something isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions