[video_player] `_playerWith` throws unrecoverable StateError when native player is destroyed by OS during CONFIGURATION_CHANGED / LOW_MEMORY

Open Beginner friendly
#190,739 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
dart
Domain
mobile

Research direction

Start with buildViewWithOptions in android_video_player.dart and avfoundation_video_player.dart, alongside the _playerWith implementations and the reported _VideoPlayerState.build call path. Verify the missing-player case during rebuilds after disposal or configuration changes. Done means both platforms return an empty widget instead of throwing when the player ID is absent.

Written by the indexing model from the issue text.

Description

p: video_player P2 package team-ecosystem triaged-ecosystem
Steps to reproduce
  1. Open a video player in fullscreen (landscape)
  2. Background the app (lock screen / home button)
  3. Wait for Android to trigger LOW_MEMORY (~40%) or iOS to reclaim AVPlayer resources
  4. Return to app → CONFIGURATION_CHANGED fires (orientation change)
  5. _VideoPlayerState.build()buildViewWithOptions(playerId)_playerWith(id) throws StateError
Expected results

buildViewWithOptions should handle missing players gracefully (return empty widget) instead of throwing.

Actual results
StateError: Bad state: No active player with ID 4.

iOS stack trace:

avfoundation_video_player.dart:327 in AVFoundationVideoPlayer._playerWith
avfoundation_video_player.dart:304 in AVFoundationVideoPlayer.buildViewWithOptions
video_player.dart:1143 in _VideoPlayerState.build

Android stack trace:

android_video_player.dart:298 in AndroidVideoPlayer._playerWith
Impact
  • 3,400+ events (2.2K iOS + 1.2K Android) from ~500 users in 30 days
  • Devices under memory pressure: OPPO Reno3 (MediaTek), Samsung A13, iPad Air 5th gen
  • Level: Error — app doesn't crash but video widget becomes unrecoverable
Root Cause

_playerWith throws when player ID is not in _players map:

// android_video_player.dart:296-298 / avfoundation_video_player.dart:325-327
_PlayerInstance _playerWith({required int id}) {
    final _PlayerInstance? player = _players[id];
    return player ?? (throw StateError('No active player with ID $id.'));
}

The race: dispose() removes from _players, but the VideoPlayer widget is still mounted (AnimatedSwitcher transition / rebuild during CONFIGURATION_CHANGED). build() calls buildViewWithOptions → throws.

Proposed Fix

Guard buildViewWithOptions to return empty widget when player is gone:

android_video_player.dart:

@override
Widget buildViewWithOptions(VideoViewOptions options) {
    final int playerId = options.playerId;
    final _PlayerInstance? player = _players[playerId];
    if (player == null) return const SizedBox.shrink();
    return _buildExoPlayerView(playerId);
}

avfoundation_video_player.dart:

@override
Widget buildViewWithOptions(VideoViewOptions options) {
    final int playerId = options.playerId;
    final _PlayerInstance? player = _players[playerId];
    if (player == null) return const SizedBox.shrink();
    final VideoPlayerViewState viewState = player.viewState;
    return switch (viewState) {
      VideoPlayerTextureViewState(:final int textureId) => Texture(textureId: textureId),
      VideoPlayerPlatformViewState() => _buildPlatformView(playerId),
    };
}
Environment
Flutter 3.44.0-3.44.6 (stable), Dart 3.12.0-3.12.2
video_player: 2.13.0, video_player_android: 2.11.0, video_player_avfoundation: 2.11.0

Tested on: OPPO Reno3 (Android 12, MediaTek MT6779), iPad Air 5th gen (iOS 26.6), iPhone 13 (iOS 26.5.2)

Dominant language
Dart
Stars
179k
Forks
31.7k
Avg merge
1d 21h
Merged PRs (30d)
413

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from flutter/flutter

All issues in flutter/flutter

Similar issues

More Dart issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.