The React Native bridge promise that never resolved
A one-line React Native bridge bug in react-native-background-geolocation from 2018, and the rule I still build agents around: fail loudly, never hang.
From 2018 · 2 min read · Published September 21, 2026
In 2018 we were building rider apps at Freebird on React Native, leaning heavily on react-native-background-geolocation from Transistor Software. It's an excellent library, and it's the kind of dependency where the JavaScript API is a thin layer over the React Native bridge and a lot of native code.
We hit a bug where calling removeListeners() on iOS would simply never finish. No error, no crash. Any code that awaited it just stopped.
The cause: a bridge promise with no resolve
React Native bridge methods hand native code a pair of callbacks, resolve and reject. If native code never calls either, the JavaScript promise stays pending forever. That's what was happening: the iOS implementation cleaned up correctly but never called its success callback.
The fix was one line:
@synchronized(listeners) { [listeners removeAllObjects]; }
[locationManager removeListeners];
success(); I opened a PR with it (#557), along with an earlier one (#492) that updated the Xcode project for newer toolchains. Neither was merged. We carried the patch locally and moved on.
Why I still think about it
A hang is the worst failure mode there is. An error tells you something went wrong and roughly where. A hang tells you nothing, and it tends to show up as a different bug somewhere downstream: a spinner that never stops, a screen that won't unmount, a background task that quietly never runs again.
Every native bridge method should resolve or reject on every code path. I now carry that into everything asynchronous we build, including AI agents:
- Every agent run has a deadline.
- Every tool call has a budget.
- Every result says whether a limit was hit.
It's the same rule, eight years later. If something can't finish, it should say so.
Related: Wrapping a native SDK in a React Native native module · An offline upload queue that never stalled, and never complained