NSInternalInconsistencyException crash when WKWebView dialog completion handler is not called during ViewController dismissal
Author: nickymalayba-lightspeedCreated May 20, 2026Updated Sep 10, 2026
LabelsType: feature request
A critical crash occurs on iOS when:
- A WKWebView presents a JavaScript dialog (
alert(),confirm(), orprompt()) - The hosting view controller is dismissed before the user interacts with the dialog
- The dialog's completion handler is never called
This triggers WebKit's fatal exception:
Fatal Exception: NSInternalInconsistencyException
Completion handler passed to -[RNCWebView webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:] was not calledReal-world impact
This crash manifests in production when:
- An app presents a modal containing a WebView
- The modal auto-dismisses after a timeout (e.g., 30 seconds)
- During the timeout window, a website embedded in the WebView calls
window.alert(),window.confirm(), orwindow.prompt() - The user doesn't interact with the dialog before the timeout fires
- The modal closes and the WebView deallocates with the completion handler still pending
- The app crashes
Platform: iOS only
Describe the solutions you came up with
The fix implements a call-once wrapper pattern with safe dealloc cleanup:
Solution Components
Add pending handler storage (iOS only)
- New property:
_pendingJSDialogCompletionHandlerto track active dialog handlers
- New property:
Implement call-once guards in three dialog methods:
runJavaScriptAlertPanelWithMessage:completionHandler:runJavaScriptConfirmPanelWithMessage:completionHandler:runJavaScriptTextInputPanelWithPrompt:completionHandler:
Each method now:
- Creates a
callOnceclosure that ensures the handler is called exactly once - Validates that a view controller is available before presenting
- Stores the handler for cleanup during dealloc
- Clears the handler reference after calling to prevent reentry
Add dealloc cleanup
- If a pending handler exists when the view is deallocated, safely invoke it on the main thread
- Prevents WebKit's fatal exception
Benefits
- ✅ Eliminates crash when modal is dismissed with pending JS dialogs
- ✅ Guarantees completion handler is called exactly once (WebKit requirement)
- ✅ Thread-safe (dispatches to main queue if necessary)
- ✅ Zero impact on normal dialog flow (user closes dialog first)
- ✅ Graceful degradation (safe fallback when view controller is unavailable)
Additional context
- Affected versions: All versions with WKWebView dialog support
- Severity: High (production crash)
- Frequency: Depends on app behavior; easily reproduced in apps with modal timeouts and WebView content
How to reproduce
- Create a React Native app with a modal that auto-dismisses after 30 seconds
- Load a website in a WKWebView inside that modal like w3schools
- Have the website call
window.alert()orwindow.confirm() - Wait 30 seconds without dismissing the dialog
- Observe: App crashes with
NSInternalInconsistencyException
Code fix reference
See attached patch for the complete implementation covering all three dialog delegate methods.
Source: react-native-webview/react-native-webview