Skip to content

[Bug]: react-native-background plugin is not working with expo 55 when prebuild the app. #578

@abdu-zeyad

Description

@abdu-zeyad

Required Reading

  • Confirmed

Plugin Version

^4.3.0

Mobile operating-system(s)

  • iOS
  • Android

Device Manufacturer(s) and Model(s)

Iphone 17 pro max

Device operating-systems(s)

ios 26.2

React Native / Expo version

{ "name": "fetch", "main": "expo-router/entry", "version": "1.0.0", "scripts": { "start": "expo start", "reset-project": "node ./scripts/reset-project.js", "android": "expo run:android", "ios": "expo run:ios", "web": "expo start --web", "lint": "expo lint" }, "dependencies": { "@react-navigation/bottom-tabs": "^7.7.3", "@react-navigation/elements": "^2.8.1", "@react-navigation/native": "^7.1.28", "expo": "~55.0.5", "expo-constants": "~55.0.7", "expo-device": "~55.0.9", "expo-font": "~55.0.4", "expo-glass-effect": "~55.0.7", "expo-image": "~55.0.6", "expo-linking": "~55.0.7", "expo-router": "~55.0.4", "expo-splash-screen": "~55.0.10", "expo-status-bar": "~55.0.4", "expo-symbols": "~55.0.5", "expo-system-ui": "~55.0.9", "expo-web-browser": "~55.0.9", "react": "19.2.0", "react-dom": "19.2.0", "react-native": "0.83.2", "react-native-background-fetch": "^4.3.0", "react-native-gesture-handler": "~2.30.0", "react-native-reanimated": "4.2.1", "react-native-safe-area-context": "~5.6.2", "react-native-screens": "~4.23.0", "react-native-web": "~0.21.0", "react-native-worklets": "0.7.2" }, "devDependencies": { "@types/react": "~19.2.2", "typescript": "~5.9.2" }, "private": true }

What happened?

When prebuild the app (expo router), the plugin is crahsed.

note: when using it with expo without expo-router it works fine.

Plugin Code and/or Config

{
  "expo": {
    "name": "fetch",
    "slug": "fetch",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/images/icon.png",
    "scheme": "fetch",
    "userInterfaceStyle": "automatic",
    "ios": {
      "icon": "./assets/expo.icon",
      "infoPlist": {
        "UIBackgroundModes": [
          "fetch",
          "processing",
          "fetch",
          "processing"
        ],
        "BGTaskSchedulerPermittedIdentifiers": [
          "com.transistorsoft.fetch",
          "com.transistorsoft.fetch"
        ]
      },
      "bundleIdentifier": "com.abdelmajed.fetch"
    },
    "android": {
      "adaptiveIcon": {
        "backgroundColor": "#E6F4FE",
        "foregroundImage": "./assets/images/android-icon-foreground.png",
        "backgroundImage": "./assets/images/android-icon-background.png",
        "monochromeImage": "./assets/images/android-icon-monochrome.png"
      },
      "predictiveBackGestureEnabled": false,
      "package": "com.abdelmajed.fetch"
    },
    "web": {
      "output": "static",
      "favicon": "./assets/images/favicon.png"
    },
    "plugins": [
      "expo-router",
      [
        "expo-splash-screen",
        {
          "backgroundColor": "#208AEF",
          "android": {
            "image": "./assets/images/splash-icon.png",
            "imageWidth": 76
          }
        }
      ],
      "react-native-background-fetch"
    ],
    "experiments": {
      "typedRoutes": true,
      "reactCompiler": true
    }
  }
}

Relevant log output

➜  fetch git:(main) ✗ npx expo prebuild
› Android package name: com.abdelmajed.fetch
› Apple bundle identifier: com.abdelmajed.fetch
✔ Created native directories
✔ Updated package.json
[react-native-background-fetch] configuring AppDelegate (swift)
✖ Prebuild failed
Error: [ios.appDelegate]: withIosAppDelegateBaseMod: Failed to match "/@UIApplicationMain/" in contents:
internal import Expo
import React
import ReactAppDependencyProvider

@main
class AppDelegate: ExpoAppDelegate {
  var window: UIWindow?

  var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
  var reactNativeFactory: RCTReactNativeFactory?

  public override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
  ) -> Bool {
    let delegate = ReactNativeDelegate()
    let factory = ExpoReactNativeFactory(delegate: delegate)
    delegate.dependencyProvider = RCTAppDependencyProvider()

    reactNativeDelegate = delegate
    reactNativeFactory = factory

#if os(iOS) || os(tvOS)
    window = UIWindow(frame: UIScreen.main.bounds)
    factory.startReactNative(
      withModuleName: "main",
      in: window,
      launchOptions: launchOptions)
#endif

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  // Linking API
  public override func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
  ) -> Bool {
    return super.application(app, open: url, options: options) || RCTLinkingManager.application(app, open: url, options: options)
  }

  // Universal Links
  public override func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
  ) -> Bool {
    let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
    return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
  }
}

class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
  // Extension point for config-plugins

  override func sourceURL(for bridge: RCTBridge) -> URL? {
    // needed to return the correct URL for expo-dev-client.
    bridge.bundleURL ?? bundleURL()
  }

  override func bundleURL() -> URL? {
#if DEBUG
    return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
#else
    return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions