rnmapbox / rnmapbox/maps

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

Open Beginner friendly
#4,260 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug 🪲
Dominant language
Kotlin
Stars
2.9k
Forks
947
Avg merge
6d 37m
Merged PRs (30d)
1

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with RNMBXImages.swift at placeholderImage and RNMBXMapView.swift at takeSnap, then run the standalone Images and MapView reproduction on iOS 26. Replace the deprecated image-context usage without force-unwrapping a missing image, and verify that map image loading and snapshotting no longer trap on iOS 26 while existing iOS behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, react-native, swift
Domain
mobile
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.