Skip to content

iOS Crash release mode : -[FlutterEngine textureFrameAvailable:] EXC_BAD_ACCESS (KERN_INVALID_ADDRESS) #185608

Closed

Description

@Tom3652

Steps to reproduce

Unfortunately i can't reproduce it, it's a crash i have received from Crashlytics.
I am attaching here the whole trace.txt

Here is the Gemini insight :

Image Image Image
// In your AppDelegate.swift or similar
import Flutter

@UIApplicationMain
class AppDelegate: FlutterAppDelegate {

    // Assuming you have a reference to your FlutterEngine or FlutterViewController
    // let flutterEngine = FlutterEngine(name: "my_engine")
    // var flutterViewController: FlutterViewController?

    override func applicationDidEnterBackground(_ application: UIApplication) {
        // Pause any Flutter rendering or intensive operations
        // This is conceptual; actual implementation depends on Flutter's API for pausing rendering
        // You might need to send a platform channel message to your Flutter code to stop drawing.
        // Example:
        // if let controller = self.flutterViewController {
        //     let channel = FlutterMethodChannel(name: "com.example.app/background", binaryMessenger: controller.binaryMessenger)
        //     channel.invokeMethod("onAppBackground", arguments: nil)
        // }

        // Or, if Flutter has a direct API for pausing rendering when backgrounded:
        // self.flutterEngine.pauseRendering() // (Hypothetical API)
    }

    override func applicationWillEnterForeground(_ application: UIApplication) {
        // Resume Flutter rendering or intensive operations
        // Example:
        // if let controller = self.flutterViewController {
        //     let channel = FlutterMethodChannel(name: "com.example.app/background", binaryMessenger: controller.binaryMessenger)
        //     channel.invokeMethod("onAppForeground", arguments: nil)
        // }

        // self.flutterEngine.resumeRendering() // (Hypothetical API)
    }
}
Image
import 'package:flutter/widgets.dart';

class MyFlutterApp extends StatefulWidget {
  @override
  _MyFlutterAppState createState() => _MyFlutterAppState();
}

class _MyFlutterAppState extends State<MyFlutterApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.inactive || state == AppLifecycleState.paused) {
      // The app is going to the background or is suspended.
      // Stop any active texture updates, video rendering, or other intensive tasks.
      // This might involve pausing a video player, stopping a game loop, etc.
      print('App is inactive/paused, stopping texture updates.');
    } else if (state == AppLifecycleState.resumed) {
      // The app is coming back to the foreground.
      // Resume any previously paused operations.
      print('App is resumed, resuming texture updates.');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(); // Your main app content
  }
}
Image

Expected results

The app should not crash

Actual results

The app is crashing

Code sample

Code sample
[Paste your code here]

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
          Crashed: com.apple.main-thread
0  Flutter                        0x23abc -[FlutterEngine textureFrameAvailable:] + 84 (ref_ptr.h:84)
1  Flutter                        0x59908 -[FlutterTextureRegistryRelay textureFrameAvailable:] + 34 (FlutterTextureRegistryRelay.mm:34)
2  video_player_avfoundation      0x5660 -[FVPFrameUpdater displayLinkFired] + 17 (FVPFrameUpdater.m:17)
3  video_player_avfoundation      0x4be4 -[FVPDisplayLinkTarget onDisplayLink:] + 33 (FVPCADisplayLink.m:33)
4  QuartzCore                     0xbe924 CA::Display::DisplayLinkItem::dispatch_(CA::SignPost::Interval<(CA::SignPost::CAEventCode)835322056>&) + 64
5  QuartzCore                     0x9bf38 CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 880
6  QuartzCore                     0xaf770 CA::Display::DisplayLink::dispatch_deferred_display_links(unsigned int) + 360
7  UIKitCore                      0x7dee4 _UIUpdateSequenceRunNext + 128
8  UIKitCore                      0x7d374 schedulerStepScheduledMainSectionContinue + 60
9  UpdateCycle                    0x1560 UC::DriverCore::continueProcessing() + 84
10 CoreFoundation                 0x68f10 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
11 CoreFoundation                 0x68e84 __CFRunLoopDoSource0 + 172
12 CoreFoundation                 0x46b30 __CFRunLoopDoSources0 + 332
13 CoreFoundation                 0x1d6d8 __CFRunLoopRun + 820
14 CoreFoundation                 0x1ca6c _CFRunLoopRunSpecificWithOptions + 532
15 GraphicsServices               0x1498 GSEventRunModal + 120
16 UIKitCore                      0x9ddf8 -[UIApplication _run] + 792
17 UIKitCore                      0x46e54 UIApplicationMain + 336
18 UIKitCore                      0x172820 -[UIScrollView contentInset] + 588
19 Runner                         0x8bb4 main + 4341402548 (AppDelegate.swift:4341402548)
20 ???                            0x18ab6ae28 (Missing)
        

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.41.7, on macOS 26.4.1 25E253 darwin-arm64, locale fr-FR) [2,2s]
    • Flutter version 3.41.7 on channel stable at /Users/foxtom/Desktop/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision cc0734ac71 (11 days ago), 2026-04-15 21:21:08 -0700
    • Engine revision 59aa584fdf
    • Dart version 3.11.5
    • DevTools version 2.54.2
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, omit-legacy-version-file, enable-lldb-debugging,
      enable-uiscene-migration

[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0) [13,2s]
    • Android SDK at /Users/foxtom/Library/Android/sdk
    • Emulator version 36.5.11.0 (build_id 15261927) (CL:N/A)
    • Platform android-36, build-tools 36.1.0
    • ANDROID_HOME = /Users/foxtom/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.10+-117844308-b1163.108)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 26.4.1) [4,4s]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 17E202
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [9ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Connected device (2 available) [6,6s]
    • macOS (desktop) • macos  • darwin-arm64   • macOS 26.4.1 25E253 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 147.0.7727.117

[✓] Network resources [299ms]
    • All expected network resources are available.

• No issues found!

Activity

  1. saurabh-mirajkar commented on Apr 27, 2026

    @saurabh-mirajkar
    Contributor

    @Tom3652 Thanks for the detailed report. This appears to be similar to #101488.

    Keeping this open for now since there isn’t enough information yet to confirm it’s the same root cause.

    Could you please share:

    • Steps to reproduce especially around video playback and app lifecycle transitions
    • video_player plugin version
    • Frequency of occurrence
  2. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    and removed
    in triagePresently being triaged by the triage team
    on Apr 27, 2026
  3. Tom3652 commented on Apr 27, 2026

    @Tom3652
    Author

    hi @saurabh-mirajkar !
    It seems similar by the consequence but i highly doubt the cause is the same.
    I am using flutter 3.41.7 and the video_player: ^2.11.1

    -> i can't reproduce it locally i have tried many times but unable to...

    Frequency of occurrence
    It happened only once for now

  4. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Apr 27, 2026
  5. saurabh-mirajkar commented on Apr 28, 2026

    @saurabh-mirajkar
    Contributor

    @Tom3652 Thanks for the additional details.

    Since this has only occurred once and is not reproducible, it’s difficult to confirm whether this is the same root cause as #101488 or a separate issue.

    For now, we’ll keep this open and labeled for further triage. If you encounter this again, please try to capture:

    • Any steps or conditions leading up to the crash (especially around video playback or app lifecycle changes)
    • Updated crash logs if available
  6. added
    c: crashStack traces logged to the console
    engineflutter/engine related. See also e: labels.
    will need additional triageThis issue or PR needs attention before being routed to secondary triage
    packageflutter/packages repository. See also p: labels.
    needs repro infoAutomated crash report whose cause isn't yet known
    and removed
    in triagePresently being triaged by the triage team
    on Apr 28, 2026
  7. 3 remaining items

  8. Piinks commented on May 4, 2026

    @Piinks
    Contributor

    team-ios SGTM, removing needs additional triage while it make its way to their triage meeting. Thanks!

  9. removed
    will need additional triageThis issue or PR needs attention before being routed to secondary triage
    on May 4, 2026
  10. added
    P2Important issues not at the top of the work list
    triaged-iosTriaged by iOS platform team
    on May 7, 2026
  11. Dhanushya-Sasidharan commented on Jun 26, 2026

    @Dhanushya-Sasidharan

    Is there any fix for this crash from video_player_avfoundation plugin? I am also facing this crash and it's not reproducible. While the production app is crashing randomly several times and the crash rate is very high in firebase crashlytics for all iOS versions from 17 to 26 versions. Also we are facing this issue after we incorporated scene delegate in our app. Kindly help me on this issue.

  12. LahaLuhem commented on Sep 1, 2026

    @LahaLuhem

    @Tom3652 @Dhanushya-Sasidharan I managed to make reprodude it deterministically.

    1. Normal flutter create ...
    2. Replace the ios/Runner/AppDelegate.swift with the variant below:
    AppDelegate.swift (self-contained)
    import Flutter
    import UIKit
    
    /// `true` takes the `allowHeadlessExecution: YES` path, which skips `destroyContext`. No crash.
    private let useExplicitHeadlessEngine = false
    
    /// Stands in for any camera or video plugin.
    private final class TickingTexture: NSObject, FlutterTexture {
      private var pixelBuffer: CVPixelBuffer?
    
      override init() {
        super.init()
        CVPixelBufferCreate(kCFAllocatorDefault, 64, 48, kCVPixelFormatType_32BGRA, nil, &pixelBuffer)
      }
    
      func copyPixelBuffer() -> Unmanaged<CVPixelBuffer>? {
        pixelBuffer.map(Unmanaged.passRetained)
      }
    }
    
    private final class ReproFlutterViewController: FlutterViewController {
      deinit { NSLog("REPRO: FlutterViewController deinit, shell teardown should have run") }
    }
    
    @main
    @objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
      /// Held on purpose: an engine outliving its view controller is what makes this deterministic.
      private var engine: FlutterEngine?
      private var texture: TickingTexture?
      private var textures: FlutterTextureRegistry?
      private var textureId: Int64?
      private var frameTimer: DispatchSourceTimer?
      private var frames = 0
      private var dismissed = false
    
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        let launched = super.application(application, didFinishLaunchingWithOptions: launchOptions)
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in self?.presentFlutter() }
    
        return launched
      }
    
      func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
        GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
      }
    
      private func presentFlutter() {
        let controller: FlutterViewController
        if useExplicitHeadlessEngine {
          let explicit = FlutterEngine(name: "repro", project: nil, allowHeadlessExecution: true)
          explicit.run()
          controller = FlutterViewController(engine: explicit, nibName: nil, bundle: nil)
        } else {
          // Its own engine, so `engineAllowHeadlessExecution` defaults to NO.
          controller = ReproFlutterViewController()
        }
    
        guard let root = Self.rootViewController() else {
          NSLog("REPRO: no root view controller")
    
          return
        }
    
        root.present(controller, animated: false) { [weak self] in
          self?.startPushingFrames(on: controller.engine)
          DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
            NSLog("REPRO: dismissing the FlutterViewController, its shell goes with it")
            controller.dismiss(animated: false) { [weak self] in
              guard let self else { return }
    
              self.dismissed = true
              NSLog("REPRO: dismissed. engine still alive: \(self.engine != nil). Frames keep coming.")
            }
          }
        }
      }
    
      private func startPushingFrames(on engine: FlutterEngine) {
        self.engine = engine
    
        // Once only: `registrar(forPlugin:)` asserts the key is unique.
        let registry = engine.registrar(forPlugin: "ShellResetRepro")?.textures()
        textures = registry
        let ticking = TickingTexture()
        texture = ticking
        textureId = registry?.register(ticking)
        NSLog("REPRO: registered texture \(textureId ?? -1)")
    
        let timer = DispatchSource.makeTimerSource(queue: DispatchQueue(label: "repro.frames"))
        timer.schedule(deadline: .now(), repeating: .milliseconds(33))
        timer.setEventHandler { [weak self] in
          guard let self, let id = self.textureId else { return }
    
          self.frames += 1
          if self.dismissed, self.frames % 15 == 0 {
            NSLog("REPRO: frame \(self.frames) pushed after dismissal")
          }
          // Reaches `-[FlutterEngine textureFrameAvailable:]`, which derefs `_shell` unguarded.
          self.textures?.textureFrameAvailable(id)
        }
        timer.resume()
        frameTimer = timer
      }
    
      private static func rootViewController() -> UIViewController? {
        let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
    
        return scene?.windows.first(where: { $0.isKeyWindow })?.rootViewController
      }
    }

    2 ways to fix it?

    1. Null-guard unregisterTexture: and textureFrameAvailable: the way registerTexture already effectively is, by routing them through the platformView getter and returning early.
    2. Notify published plugins on the destroyContext path, so a plugin can stop producing frames deliberately instead of racing. More complete, since a plugin currently gets no signal at all.
  13. cbracken commented on Sep 9, 2026

    @cbracken
    Member

    I've got a patch out in #192465 that I believe should fix this.

    The callback in question is happening on the raster thread and [FlutterEngine destroyContext] happens on the platform thread and there's currently no synchronisation happening on the state in question, so I'll need to send a followup, but this should help.

    Edit: on further digging, I'm misremembering. This callback does happen on the platform thread, as does destroyContext teardown, so my patch should fix this crash. It was copyPixelBuffer that's fired on the raster thread.

    As @LahaLuhem mentions, we really should have a teardown notification for plugins that need to manage their state but the embedder should also handle things gracefully.

  14. github-actions commented on Sep 24, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  15. locked as resolved and limited conversation to collaborators on Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: crashStack traces logged to the consoleengineflutter/engine related. See also e: labels.needs repro infoAutomated crash report whose cause isn't yet knownp: video_playerThe Video Player pluginpackageflutter/packages repository. See also p: labels.team-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions