Repository: flutter
Issue: "Failed assertion: line 207 pos 12: '_overlay != null': is not true" when trying to remove a non null overlayEntry
Labels: framework,a: error message,has reproducible steps,P2,team-framework,triaged-framework,found in release: 3.19,found in release: 3.21

This issue has been surfing for a while, I am unsure if it's an error in the code sample shared below or an error in the framework, But it looks like it's the latter looking at the logs and I was able to reproduce this without any external package.

originally filed here https://github.com/maheshmnj/searchfield/issues/43

### Steps to reproduce

1. Run the below code sample
2. Tap the textfield
3. select one of the displayed option

### Expected results

Overlay entry can be removed and the app runs without the error.

### Actual results

An assertion error is thrown when trying to remove the overlay entry when it is not null and mounted

```dart
 if (_overlayEntry != null && _overlayEntry!.mounted) {
      _overlayEntry!.remove();
    }
```

### Code sample

<details open><summary>Code sample</summary>

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Material App',
      home: BottomNavBarHome(),
    );
  }
}

class PageOne extends StatefulWidget {
  const PageOne({Key? key, required this.bottomNavBarKey}) : super(key: key);

  final GlobalKey<State<BottomNavigationBar>> bottomNavBarKey;

  @override
  State<PageOne> createState() => _PageOneState();
}

class _PageOneState extends State<PageOne> {
  final ScrollController _scrollController = ScrollController();
  BottomNavigationBar? bottomNavKey;

  Widget _list() {
    return Container(
      height: 5 * 40,
      child: Scrollbar(
          controller: _scrollController,
          thumbVisibility: true,
          child: ListView.builder(
              controller: _scrollController,
              padding: EdgeInsets.zero,
              itemCount: 20,
              itemBuilder: (context, index) => ListTile(
                    title: Text('item $index'),
                    onTap: () {
                      _searchFocus.unfocus();
                      if (widget.bottomNavBarKey.currentWidget != null) {
                        bottomNavKey = widget.bottomNavBarKey.currentWidget
                            as BottomNavigationBar;
                      }
                      bottomNavKey?.onTap!(1);
                    },
                  ))),
    );
  }

  final LayerLink _layerLink = LayerLink();

  OverlayEntry _createOverlay() {
    final renderBox = context.findRenderObject() as RenderBox;
    final size = renderBox.size;
    final offset = renderBox.localToGlobal(Offset.zero);
    return OverlayEntry(
        builder: (context) => Positioned(
              left: offset.dx,
              width: size.width,
              child: CompositedTransformFollower(
                  offset: Offset(0, 50),
                  link: _layerLink,
                  child: Material(color: Colors.red, child: _list())),
            ));
  }

  OverlayEntry? _overlayEntry;

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _overlayEntry = _createOverlay();
    });
    _searchFocus = FocusNode();
    _searchFocus.addListener(() {
      if (!_searchFocus.hasFocus) {
        if (_overlayEntry != null && _overlayEntry!.mounted) {
          _overlayEntry!.remove();
        }
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    if (_overlayEntry != null && _overlayEntry!.mounted) {
      _overlayEntry!.remove();
    }
    _searchFocus.dispose();
    super.dispose();
  }

  late FocusNode _searchFocus;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Steps to Reproduce'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CompositedTransformTarget(
              link: _layerLink,
              child: TextFormField(
                focusNode: _searchFocus,
                decoration: InputDecoration(
                  focusedBorder: OutlineInputBorder(
                    borderSide: BorderSide(
                      color: Colors.black.withOpacity(0.8),
                    ),
                  ),
                  border: OutlineInputBorder(
                    borderSide: BorderSide(color: Colors.red),
                  ),
                ),
                onTap: () {
                  Overlay.of(context).insert(_overlayEntry!);
                },
                onChanged: (query) {},
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class BottomNavBarHome extends StatefulWidget {
  const BottomNavBarHome({Key? key}) : super(key: key);

  @override
  State<BottomNavBarHome> createState() => _BottomNavBarHomeState();
}

class _BottomNavBarHomeState extends State<BottomNavBarHome> {
  late PageController _pageController;
  late final GlobalKey<State<BottomNavigationBar>> _bottomNavBarKey;
  DateTime? currentBackPressTime;
  @override
  void initState() {
    _pageController = PageController();
    _bottomNavBarKey = GlobalKey<State<BottomNavigationBar>>();
    super.initState();
  }

  int selectindex = 0;
  void _onItemTapped(int selectedIndex) {
    setState(() {
      selectindex = selectedIndex;
      _pageController.jumpToPage(selectindex);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Scaffold(
        extendBody: true,
        body: PageView(
          controller: _pageController,
          children: [
            PageOne(
              bottomNavBarKey: _bottomNavBarKey,
            ),
            PageSecond(),
            PageThird(),
          ],
          // onPageChanged: _onPageChanged,
        ),
        bottomNavigationBar: BottomNavigationBar(
          currentIndex: selectindex,
          type: BottomNavigationBarType.fixed,
          key: _bottomNavBarKey,
          onTap: _onItemTapped,
          items: const [
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'Page 1',
              backgroundColor: Colors.blue,
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.person),
              label: 'Page 2',
              backgroundColor: Colors.blue,
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.book),
              label: 'Page 3',
              backgroundColor: Colors.blue,
            ),
          ],
        ),
      ),
    );
  }
}

class PageSecond extends StatelessWidget {
  const PageSecond({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: Text('Page Second')),
    );
  }
}

class PageThird extends StatelessWidget {
  const PageThird({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
          child: Text(
        'Page Third',
      )),
    );
  }
}

```

</details>


### Screenshots or Video

<details open>
<summary>Screenshots / Video demonstration</summary>

[Upload media here]

</details>


### Logs

<details open><summary>Logs</summary>

```console
Restarted application in 2,512ms.
D/EGL_emulation( 6657): app_time_stats: avg=98101.58ms min=98101.58ms max=98101.58ms count=1
D/InputMethodManager( 6657): showSoftInput() view=io.flutter.embedding.android.FlutterView{6bfaeb4 VFE...... .F...... 0,0-1440,3064 #1 aid=1073741824} flags=0 reason=SHOW_SOFT_INPUT
W/example.exampl( 6657): Reducing the number of considered missed Gc histogram windows from 226 to 100
D/InsetsController( 6657): show(ime(), fromIme=true)
D/EGL_emulation( 6657): app_time_stats: avg=5986.86ms min=4.82ms max=119620.28ms count=20
D/EGL_emulation( 6657): app_time_stats: avg=1997.25ms min=1997.25ms max=1997.25ms count=1
D/EGL_emulation( 6657): app_time_stats: avg=136.85ms min=17.84ms max=500.48ms count=8
D/EGL_emulation( 6657): app_time_stats: avg=93.36ms min=5.94ms max=1493.54ms count=18

════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
'package:flutter/src/widgets/overlay.dart': Failed assertion: line 207 pos 12: '_overlay != null': is not true.

When the exception was thrown, this was the stack:
#2      OverlayEntry.remove (package:flutter/src/widgets/overlay.dart:207:12)
#3      _PageOneState.dispose (package:example/main.dart:92:22)
#4      StatefulElement.unmount (package:flutter/src/widgets/framework.dart:5867:11)
#5      _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2097:13)
#6      _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2095:7)
#7      SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:6940:14)
#8      _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2093:13)
#9      _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2095:7)
#10     SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:6940:14)
#11     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2093:13)
#12     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2095:7)
#13     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:5704:14)
#14     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2093:13)
#15     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2095:7)
#16     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:5704:14)
#17     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2093:13)
#18     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2095:7)
#19     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:5704:14)
#20     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2093:13)
#21     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2095:7)
#22     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:5704:14)
#23     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2093:13)
#24     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:2095:7)
#25     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:5704:14)
#26     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:2093:13)
#27     ListIterable.forEach (dart:_internal/iterable.dart:49:13)
#28     _InactiveElements._unmountAll (package:flutter/src/widgets/framework.dart:2106:25)
#29     BuildOwner.lockState (package:flutter/src/widgets/framework.dart:2799:15)
#30     BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:3234:7)
#31     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:992:19)
#32     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:448:5)
#33     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1386:15)
#34     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1311:9)
#35     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1169:5)
#36     _invoke (dart:ui/hooks.dart:312:13)
#37     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:399:5)
#38     _drawFrame (dart:ui/hooks.dart:283:31)
(elided 2 frames from class _AssertionError)
════════════════════════════════════════════════════════════════════════════════
D/EGL_emulation( 6657): app_time_stats: avg=3216.29ms min=692.67ms max=5739.90ms count=2

```

</details>


### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
mahesh@Maheshs-MacBook-Air-M1-3 searchfield % flutter doctor -v
Could not load custom device from config index 0: Expected enabled to be a boolean.
[✓] Flutter (Channel stable, 3.19.3, on macOS 14.3.1 23D60 darwin-arm64, locale en-IN)
    • Flutter version 3.19.3 on channel stable at /Users/mahesh/Development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision ba39319843 (13 days ago), 2024-03-07 15:22:21 -0600
    • Engine revision 2e4ba9c6fb
    • Dart version 3.3.1
    • DevTools version 2.31.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc4)
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-34, build-tools 33.0.0-rc4
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15A507
    • CocoaPods version 1.14.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

[✓] VS Code (version 1.86.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.84.0

[✓] VS Code (version 1.79.0-insider)
    • VS Code at /Applications/Visual Studio Code - Insiders.app/Contents
    • Flutter extension version 3.80.0

[✓] Connected device (3 available)
    • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64  • Android 12 (API 31)
      (emulator)
    • macOS (desktop)             • macos         • darwin-arm64   • macOS 14.3.1 23D60
      darwin-arm64
    • Chrome (web)                • chrome        • web-javascript • Google Chrome
      120.0.6099.71

[!] Network resources
    ✗ An HTTP error occurred while checking "https://maven.google.com/": Connection closed
      before full header was received
    ✗ An HTTP error occurred while checking "https://github.com/": Connection closed before
      full header was received

! Doctor found issues in 1 category.
```

</details>