Repository navigation
iOS: a partial swipe-down on the photo picker sheet cancels the pick, and the later selection is dropped #2243
Description
Describe the bug
On iOS, with file_picker 13.1.0, if the user starts to swipe the picker sheet down and then lets it spring back, pickFiles completes right away with an empty list, as if the user had cancelled. The picker stays open. If the user then selects files and confirms, nothing is returned for them: pickFiles has already completed.
I reproduced this with the photo picker (FileType.media). I couldn't reproduce it with the document picker (FileType.any).
Platform
- Android
- iOS
- Web
- Desktop
Platform OS version
- iOS 26.6 (physical device)
- iOS 17.5 (simulator; see video below)
How are you picking?
Here's code for a sample app you can use to reproduce the issue:
sample app
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: ReproPage()));
class ReproPage extends StatefulWidget {
const ReproPage({super.key});
@override
State<ReproPage> createState() => _ReproPageState();
}
class _ReproPageState extends State<ReproPage> {
final List<String> _log = [];
void _addLog(String line) {
final now = DateTime.now();
final time = [now.hour, now.minute, now.second]
.map((n) => n.toString().padLeft(2, '0')).join(':');
setState(() => _log.add('$time $line'));
}
Future<void> _pick(FileType type) async {
_addLog('pickFiles(type: ${type.name}) called');
try {
final files = await FilePicker.pickFiles(type: type);
_addLog('pickFiles returned ${files.length} file(s)'
'${files.isEmpty ? '' : ': ${files.map((f) => f.name).join(', ')}'}');
} catch (e) {
_addLog('pickFiles threw: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('file_picker swipe repro')),
body: Column(children: [
Padding(
padding: const EdgeInsets.all(16),
child: Wrap(spacing: 16, children: [
ElevatedButton(
onPressed: () => _pick(FileType.media),
child: const Text('Pick media')),
ElevatedButton(
onPressed: () => _pick(FileType.any),
child: const Text('Pick any file')),
])),
Expanded(child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16),
children: [for (final line in _log) Text(line)])),
]));
}
}Details to reproduce the issue
flutter create --platforms=ios file_picker_swipe_repro, thencd file_picker_swipe_repro.flutter pub add file_picker:13.1.0.- Replace
lib/main.dartwith the code above. - Run it on an iOS device:
flutter run. - Tap Pick media. The photo picker opens as a sheet.
- Put a finger on the sheet's top bar (not on the photo grid, which scrolls instead). Drag down about a third of the screen, and let go so the sheet springs back. The picker stays open.
- Select a photo, and tap Add.
Expected: nothing is logged at step 6. After step 7, the log shows pickFiles returned 1 file(s): … with the photo's name.
Actual: at step 6, the log already shows pickFiles returned 0 file(s). At step 7 the picker closes, but nothing more is logged: the selection is lost.
With Pick any file (the document picker), the equivalent steps work as expected.
Error Log
N/A
Screenshots and/or video
Screen.Recording.2026-10-09.at.3.06.15.PM.mov
Flutter Version details
Details
$ flutter doctor -v
[✓] Flutter (Channel main, 3.49.0-1.0.pre-209, on macOS 26.5.1 25F80 darwin-arm64, locale en-US) [2.9s]
• Flutter version 3.49.0-1.0.pre-209 on channel main at /Users/chrisbobbe/.local/lib/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 3a8e191c9e (10 days ago), 2026-09-29 18:38:24 +0000
• Engine revision 9c931498d5
• Dart version 3.14.0 (build 3.14.0-271.0.dev)
• DevTools version 2.61.0-dev.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations,
enable-native-assets, enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration,
enable-riscv64, enable-hcpp
[!] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [2.2s]
• Android SDK at /Users/chrisbobbe/Library/Android/sdk
• Emulator version 36.1.9.0 (build_id 13823996) (CL:N/A)
• Platform android-36, build-tools 36.0.0
• ANDROID_HOME = /Users/chrisbobbe/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)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 26.6) [953ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17F113
• CocoaPods version 1.17.0
[✓] Chrome - develop for the web [4ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (4 available) [6.4s]
• Chris’s iPhone (mobile) • <redacted> • ios • iOS 26.6.2 23G90
• iPhone 15 Pro (mobile) • D2E5855E-A059-4FBB-A9AF-117C12378F4F • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-5 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 26.5.1 25F80 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 155.0.8059.39
[✓] Network resources [288ms]
• All expected network resources are available.
! Doctor found issues in 1 category.
Additional context
I may post a diagnosis from Claude Code, below, which I haven't confirmed, but that might still be helpful to someone who's already familiar with the code it touches on.
Activity
chrisbobbe commentedon Oct 9, 2026
As foreshadowed in the issue description—
—here's a copy-pasted diagnosis from a Claude Code session, in case it's helpful:
Details
vicajilau commentedon Oct 10, 2026
Thanks a lot for the excellent report, the repro app and the diagnosis! 🙌 Everything checked out against the code.
As you suggested,
presentationControllerWillDismissnow waits for the dismissal transition to end through thetransitionCoordinator, and only finishes the request if it wasn't cancelled. So a partial swipe that springs back keeps the pick open and the later selection is returned, while a completed dismissal, including the fast swipe from #2021, still cancels it.The fix is in #2244. We reproduced the bug with your sample app and confirmed the fix with it on the simulator. It will ship in
file_picker_darwin2.1.4, and withfile_picker13.1.0 a regularflutter pub upgradewill pick it up.vicajilau commentedon Oct 11, 2026
The fix is now published in
file_picker_darwin2.1.4. Withfile_picker13.1.0 a regularflutter pub upgradepicks it up. Thanks again @chrisbobbe! 🙌Keep the iOS pick open when a swipe down is cancelled
deps: Upgrade file_picker to 13.1.0, with the packages that requires
deps: Upgrade file_picker to 13.1.0, with the packages that requires
deps: Upgrade file_picker to 13.1.0, with the packages that requires