Skip to content

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

Description

@angelolencina

Environment

  • @rnmapbox/maps 10.3.0 (checked 10.3.2, same code there)
  • react-native 0.82.1, new arch
  • 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)
   }
 }

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