firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.73k stars 3.98k forks source link

🐛 [firebase_storage] Unhandled Exception: type ‘Null’ is not a subtype of type ‘FutureOr<TaskSnapshotPlatform>’ #6776

Closed Tom3652 closed 2 years ago

Tom3652 commented 3 years ago

Bug report

Describe the bug Uploading a multiple local files simultaneously (6) to Firebase Storage sometimes lead to a server error. I have checked that the file exists before using the reference.putFile(file) method. I have done the test 10 times in a row, files that go in error are not always the same either but there is always an error among the files. The files are in full HD (1920x1080).

This seems to happen only on IOS but i have not tested it on Android.

Steps to reproduce

Steps to reproduce the behavior:

  1. Upload multiple local (full HD) files at least 5 or 6 at the same time.
  2. See the error happening 1 or 2 times.

This may be hard to reproduce but with a 300ko/s internet connection speed it's 100% happening, not sure this is related however.

Expected behavior

Firebase storage should not have an unknown error as is it said in the Logs (see below).


Additional context

2021-08-08 16:54:22.382657+0200 Runner[53915:1649191] flutter: Error is : [firebase_storage/unknown] An unknown error occurred, please check the server response.
2021-08-08 16:54:22.383513+0200 Runner[53915:1649191] [VERBOSE-2:ui_dart_state.cc(199)] Unhandled Exception: type ‘Null’ is not a subtype of type ‘FutureOr<TaskSnapshotPlatform>’
#0   _FutureListener.handleError (dart:async/future_impl.dart:172:20)
#1   Future._propagateToListeners.handleError (dart:async/future_impl.dart:719:47)
#2   Future._propagateToListeners (dart:async/future_impl.dart:740:24)
#3   Future._completeError (dart:async/future_impl.dart:550:5)
#4   Future._asyncCompleteError.<anonymous closure> (dart:async/future_impl.dart:606:7)
#5   _rootRun (dart:async/zone.dart:1354:13)
#6   _CustomZone.run (dart:async/zone.dart:1258:19)
#7   _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
#8   _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
#9   _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#10   _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand ``` Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 2.2.3, on macOS 11.5.1 20G80 darwin-x64, locale fr-FR) [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3) [✓] Xcode - develop for iOS and macOS [✓] Chrome - develop for the web [!] Android Studio (version 2020.3) ✗ Unable to find bundled Java version. [✓] Connected device (3 available) ! Doctor found issues in 1 category. ```

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand ``` Dart SDK 2.13.4 Flutter SDK 2.2.3 testapp 1.0.0+1 dependencies: - app_tracking_transparency 2.0.1 [flutter] - badges 2.0.1 [flutter] - better_player 0.0.72 [flutter cupertino_icons wakelock pedantic meta flutter_widget_from_html_core visibility_detector path_provider collection xml] - cached_network_image 3.1.0 [flutter flutter_cache_manager octo_image cached_network_image_platform_interface cached_network_image_web] - camera 0.8.1+7 [camera_platform_interface flutter pedantic quiver] - circular_menu 1.2.3 [flutter] - clipboard 0.1.3 [flutter] - cloud_firestore 2.4.0 [cloud_firestore_platform_interface cloud_firestore_web firebase_core firebase_core_platform_interface flutter meta] - cloud_functions 3.0.0 [cloud_functions_platform_interface cloud_functions_web firebase_core firebase_core_platform_interface flutter] - connectivity 3.0.6 [flutter meta connectivity_platform_interface connectivity_macos connectivity_for_web] - country_code_picker 2.0.2 [flutter modal_bottom_sheet collection universal_platform] - crypto 3.0.1 [collection typed_data] - cupertino_back_gesture 0.1.0 [flutter] - cupertino_icons 1.0.3 - extended_image 4.1.0 [extended_image_library flutter meta] - extended_tabs 2.3.0 [flutter] - firebase_analytics 8.2.0 [firebase_analytics_platform_interface firebase_analytics_web firebase_core flutter meta] - firebase_app_check 0.0.1+3 [firebase_app_check_platform_interface firebase_app_check_web firebase_core firebase_core_platform_interface flutter] - firebase_auth 3.0.1 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta] - firebase_core 1.4.0 [firebase_core_platform_interface firebase_core_web flutter meta] - firebase_crashlytics 2.1.1 [firebase_core firebase_core_platform_interface firebase_crashlytics_platform_interface flutter stack_trace] - firebase_database 7.1.2 [firebase_core flutter] - firebase_dynamic_links 2.0.7 [firebase_core flutter] - firebase_in_app_messaging 0.5.0+7 [firebase_core flutter meta] - firebase_messaging 10.0.4 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta] - firebase_performance 0.7.0+7 [firebase_core flutter] - firebase_storage 10.0.1 [firebase_core firebase_core_platform_interface firebase_storage_platform_interface firebase_storage_web flutter] - flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine] - flutter_app_badger 1.2.0 [flutter] - flutter_arc_text 0.5.0 [characters flutter] - flutter_cache_manager 3.1.2 [clock collection file flutter http path path_provider pedantic rxdart sqflite uuid] - flutter_contacts 1.1.0+3 [flutter] - flutter_facebook_auth 3.5.0 [flutter flutter_facebook_auth_platform_interface flutter_facebook_auth_web] - flutter_ffmpeg 0.4.2 [flutter] - flutter_image_compress 1.1.0 [flutter] - flutter_local_notifications 8.1.1 [flutter flutter_local_notifications_platform_interface platform timezone] - flutter_localizations 0.0.0 [flutter intl characters clock collection meta path typed_data vector_math] - flutter_sound_lite 8.3.9 [path_provider recase uuid provider flutter_spinkit path synchronized logger flutter flutter_sound_platform_interface flutter_sound_web] - flutter_staggered_grid_view 0.4.0 [flutter] - flutter_svg 0.22.0 [flutter meta path_drawing vector_math xml] - fluttertoast 8.0.8 [flutter flutter_web_plugins] - geocoding 2.0.0 [flutter geocoding_platform_interface] - geolocator 7.4.0 [flutter geolocator_platform_interface geolocator_android geolocator_apple geolocator_web] - google_maps_flutter 2.0.6 [flutter flutter_plugin_android_lifecycle google_maps_flutter_platform_interface] - google_mobile_ads 0.13.3 [meta flutter] - google_sign_in 5.0.7 [flutter google_sign_in_platform_interface google_sign_in_web meta] - image_editor 1.0.0 [flutter] - in_app_review 2.0.2 [flutter in_app_review_platform_interface] - intl 0.17.0 [clock path] - light_compressor 1.1.1 [flutter] - modal_bottom_sheet 2.0.0 [flutter] - path 1.8.0 - path_provider 2.0.2 [flutter path_provider_platform_interface path_provider_macos path_provider_linux path_provider_windows] - permission_handler 8.1.4+2 [flutter meta permission_handler_platform_interface] - photo_manager 1.3.1 [flutter] - progressive_image 2.0.0 [flutter] - provider 5.0.0 [collection flutter nested] - pull_to_refresh 2.0.0 [flutter] - rive 0.7.27 [collection flutter graphs http meta] - scroll_to_index 2.0.0 [flutter] - share_plus 2.1.4 [meta mime flutter share_plus_platform_interface share_plus_linux share_plus_macos share_plus_windows share_plus_web] - shared_preferences 2.0.6 [meta flutter shared_preferences_platform_interface shared_preferences_linux shared_preferences_macos shared_preferences_web shared_preferences_windows] - sign_in_with_apple 3.0.0 [flutter meta] - sliver_tools 0.2.5 [flutter] - url_launcher 6.0.9 [flutter meta url_launcher_linux url_launcher_macos url_launcher_platform_interface url_launcher_web url_launcher_windows] - uuid 3.0.4 [crypto] - video_player 2.1.12 [flutter flutter_test meta video_player_platform_interface video_player_web] - visibility_detector 0.2.0 [flutter] - volume_watcher 2.0.1 [flutter] - webview_flutter 2.0.10 [flutter] dev dependencies: - flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data] transitive dependencies: - async 2.6.1 [meta collection] - boolean_selector 2.1.0 [source_span string_scanner] - cached_network_image_platform_interface 1.0.0 [flutter flutter_cache_manager] - cached_network_image_web 1.0.1 [flutter flutter_cache_manager cached_network_image_platform_interface] - camera_platform_interface 2.1.0 [cross_file flutter meta plugin_platform_interface stream_transform] - characters 1.1.0 - charcode 1.2.0 - clock 1.1.0 - cloud_firestore_platform_interface 5.3.0 [collection firebase_core flutter meta plugin_platform_interface] - cloud_firestore_web 2.3.0 [cloud_firestore_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js] - cloud_functions_platform_interface 5.0.8 [firebase_core flutter meta plugin_platform_interface] - cloud_functions_web 4.0.10 [cloud_functions_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js] - collection 1.15.0 - connectivity_for_web 0.4.0 [connectivity_platform_interface flutter_web_plugins flutter] - connectivity_macos 0.2.0 [flutter] - connectivity_platform_interface 2.0.1 [flutter meta plugin_platform_interface] - cross_file 0.3.1+4 [flutter meta] - csslib 0.17.0 [source_span] - extended_image_library 3.1.0 [crypto flutter http_client_helper path path_provider] - fake_async 1.2.0 [clock collection] - ffi 1.1.2 - file 6.1.2 [meta path] - firebase 9.0.1 [http http_parser js] - firebase_analytics_platform_interface 2.0.1 [flutter meta] - firebase_analytics_web 0.3.0+1 [firebase firebase_analytics_platform_interface flutter flutter_web_plugins meta] - firebase_app_check_platform_interface 0.0.1+3 [firebase_core flutter meta plugin_platform_interface] - firebase_app_check_web 0.0.1+3 [firebase_app_check_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js] - firebase_auth_platform_interface 6.0.0 [firebase_core flutter meta plugin_platform_interface] - firebase_auth_web 3.0.0 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser intl js meta] - firebase_core_platform_interface 4.0.1 [collection flutter meta plugin_platform_interface] - firebase_core_web 1.1.0 [firebase_core_platform_interface flutter flutter_web_plugins js meta] - firebase_crashlytics_platform_interface 3.1.0 [collection firebase_core flutter meta plugin_platform_interface] - firebase_messaging_platform_interface 3.0.3 [firebase_core flutter meta plugin_platform_interface] - firebase_messaging_web 2.0.3 [firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins js meta] - firebase_storage_platform_interface 4.0.0 [collection firebase_core flutter meta plugin_platform_interface] - firebase_storage_web 3.0.0 [async firebase_core firebase_core_web firebase_storage_platform_interface flutter flutter_web_plugins http js meta] - flutter_blurhash 0.6.0 [flutter meta pedantic] - flutter_facebook_auth_platform_interface 2.7.0 [flutter plugin_platform_interface] - flutter_facebook_auth_web 2.6.0+2 [flutter flutter_web_plugins js flutter_facebook_auth_platform_interface] - flutter_local_notifications_platform_interface 4.0.1 [flutter plugin_platform_interface] - flutter_plugin_android_lifecycle 2.0.2 [flutter] - flutter_sound_platform_interface 8.3.9 [flutter meta plugin_platform_interface logger] - flutter_sound_web 8.3.9 [flutter_sound_platform_interface flutter logger flutter_web_plugins meta js] - flutter_spinkit 5.0.0 [flutter] - flutter_web_plugins 0.0.0 [flutter js characters collection meta typed_data vector_math] - flutter_widget_from_html_core 0.6.1+4 [csslib flutter html] - geocoding_platform_interface 2.0.0 [flutter meta plugin_platform_interface] - geolocator_android 1.0.0 [flutter geolocator_platform_interface] - geolocator_apple 1.0.0 [flutter geolocator_platform_interface] - geolocator_platform_interface 2.3.2 [flutter plugin_platform_interface vector_math meta] - geolocator_web 2.0.6 [flutter flutter_web_plugins geolocator_platform_interface] - google_maps_flutter_platform_interface 2.1.0 [collection flutter meta plugin_platform_interface stream_transform] - google_sign_in_platform_interface 2.0.1 [flutter meta quiver] - google_sign_in_web 0.10.0+1 [flutter flutter_web_plugins google_sign_in_platform_interface js meta] - graphs 2.0.0 - html 0.15.0 [csslib source_span] - http 0.13.3 [async http_parser meta path pedantic] - http_client_helper 2.0.2 [http] - http_parser 4.0.0 [charcode collection source_span string_scanner typed_data] - in_app_review_platform_interface 2.0.2 [flutter url_launcher plugin_platform_interface platform] - js 0.6.3 - logger 1.0.0 - matcher 0.12.10 [stack_trace] - meta 1.3.0 - mime 1.0.0 - nested 1.0.0 [flutter] - octo_image 1.0.0+1 [flutter flutter_blurhash] - path_drawing 0.5.1 [vector_math meta path_parsing flutter] - path_parsing 0.2.1 [vector_math meta] - path_provider_linux 2.0.2 [flutter path path_provider_platform_interface xdg_directories] - path_provider_macos 2.0.2 [flutter] - path_provider_platform_interface 2.0.1 [flutter meta platform plugin_platform_interface] - path_provider_windows 2.0.3 [ffi flutter meta path path_provider_platform_interface win32] - pedantic 1.11.1 - permission_handler_platform_interface 3.6.1 [flutter meta plugin_platform_interface] - petitparser 4.1.0 [meta] - platform 3.0.0 - plugin_platform_interface 2.0.1 [meta] - process 4.2.3 [file path platform] - quiver 3.0.1 [matcher] - recase 4.0.0 - rxdart 0.27.1 - share_plus_linux 2.0.3 [share_plus_platform_interface file flutter meta url_launcher] - share_plus_macos 2.0.2 [share_plus_platform_interface flutter] - share_plus_platform_interface 2.0.1 [flutter meta mime plugin_platform_interface] - share_plus_web 2.0.4 [share_plus_platform_interface url_launcher flutter flutter_web_plugins meta] - share_plus_windows 2.0.3 [share_plus_platform_interface flutter meta url_launcher] - shared_preferences_linux 2.0.2 [file meta flutter path path_provider_linux shared_preferences_platform_interface] - shared_preferences_macos 2.0.2 [flutter shared_preferences_platform_interface] - shared_preferences_platform_interface 2.0.0 [flutter] - shared_preferences_web 2.0.1 [flutter flutter_web_plugins meta shared_preferences_platform_interface] - shared_preferences_windows 2.0.2 [flutter file meta path path_provider_platform_interface path_provider_windows shared_preferences_platform_interface] - sky_engine 0.0.99 - source_span 1.8.1 [collection path term_glyph] - sqflite 2.0.0+3 [flutter sqflite_common path] - sqflite_common 2.0.0+2 [synchronized path meta] - stack_trace 1.10.0 [path] - stream_channel 2.1.0 [async] - stream_transform 2.0.0 - string_scanner 1.1.0 [charcode source_span] - synchronized 3.0.0 - term_glyph 1.2.0 - test_api 0.3.0 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher] - timezone 0.7.0 [path] - typed_data 1.3.0 [collection] - universal_platform 1.0.0+1 - url_launcher_linux 2.0.1 [flutter] - url_launcher_macos 2.0.1 [flutter] - url_launcher_platform_interface 2.0.4 [flutter plugin_platform_interface] - url_launcher_web 2.0.2 [flutter flutter_web_plugins meta url_launcher_platform_interface] - url_launcher_windows 2.0.1 [flutter] - vector_math 2.1.0 - video_player_platform_interface 4.1.0 [flutter meta flutter_test] - video_player_web 2.0.2 [flutter flutter_web_plugins meta video_player_platform_interface] - wakelock 0.5.3+3 [flutter meta wakelock_macos wakelock_platform_interface wakelock_web wakelock_windows] - wakelock_macos 0.1.0+2 [flutter flutter_web_plugins wakelock_platform_interface] - wakelock_platform_interface 0.2.1+2 [flutter meta] - wakelock_web 0.2.0+2 [flutter flutter_web_plugins js wakelock_platform_interface] - wakelock_windows 0.1.0+1 [flutter wakelock_platform_interface win32] - win32 2.2.5 [ffi] - xdg_directories 0.2.0 [meta path process] - xml 5.1.2 [collection meta petitparser] ```

darshankawar commented 3 years ago

Uploading a multiple local files simultaneously (6) to Firebase Storage sometimes lead to a server error.

@Tom3652 What do you exactly mean by uploading multiple files simultaneously ?

I tried with the official plugin example on latest master version using iPhone 6s device and uploaded 6 full HD 1920 x 1080 images one by one which were uploaded without any issues.

console log ``` Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' flutter: test/audio session.wav/playground/some-image.jpg BackgroundSession <155FA715-EF4C-4707-99CC-2AC7B4C7608F> connection to background transfer daemon invalidated [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' flutter: test/audio session.wav/playground/some-image.jpg BackgroundSession connection to background transfer daemon invalidated [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' flutter: test/audio session.wav/playground/some-image.jpg BackgroundSession connection to background transfer daemon invalidated [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' flutter: test/audio session.wav/playground/some-image.jpg BackgroundSession <83F0E433-CA2D-40BD-9237-3512575417F8> connection to background transfer daemon invalidated [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' flutter: test/audio session.wav/playground/some-image.jpg BackgroundSession <6A1FFF1D-E4D1-4441-9DA2-6726E3930207> connection to background transfer daemon invalidated [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' flutter: test/audio session.wav/playground/some-image.jpg BackgroundSession <227CA624-039A-4AB2-863D-87CBA24D4016> connection to background transfer daemon invalidated [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' [Runner] findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic' flutter: test/audio session.wav/playground/some-image.jpg BackgroundSession connection to background transfer daemon invalidated ```
Screenshot 2021-08-09 at 3 19 36 PM
flutter doctor -v ``` [✓] Flutter (Channel master, 2.5.0-6.0.pre.29, on Mac OS X 10.15.4 19E2269 darwin-x64, locale en-GB) • Flutter version 2.5.0-6.0.pre.29 at /Users/dhs/documents/fluttersdk/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 6876c52b5b (11 hours ago), 2021-08-08 15:34:09 -0700 • Engine revision c0e59bc7b6 • Dart version 2.14.0 (build 2.14.0-383.0.dev) [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 12.3, Build version 12C33 • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.58.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (4 available) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 92.0.4515.131 • No issues found! ```

If this doesn't represent your use case, please provide a complete code sample that we can use to verify this issue.

Tom3652 commented 3 years ago

Hello @darshankawar, thanks for taking time to test it.

Simultaneously means that i have 6 UploadTask instances running at the same time.

I have tried on my physical phones i was able to reproduce the issue only once out of 10 retries today (with 10 files not 6), and my phone was actually getting very hot...

However, on IOS simulator (iphone 12 Pro Max), with the 6 given files it's 100% in error with 10 retries while the 6 are uploading at the same time.

-> 2-3 files are always in error with this pattern

I am not using the image_picker package, the photo_manager package but the files are retrieved correctly and exists before the upload so i don't think this changes anything. I am saving the temporary files in the app Cache directory thanks to await getTemporaryDirectory() with a unique timestamp. I could not make the firebase_storage example working on IOS VMs either, i have files exception even before the upload.

My guess is that this happens when the files can't be read properly during the upload due to some I/O operations, because "sometimes" after the error is raised (in the middle of the upload), the File(file).existSync() returns false but the file exists.

Sometimes too, i am able to retry the upload with success, sometimes my check tells me that the file doesn't exist anymore.

Maybe this is due an automated mecanism to clear the cache app directory ? (not in my code i mean)

darshankawar commented 3 years ago

[firebase_storage/unknown] An unknown error occurred, please check the server response.

This seems to be an error coming from storage exceptions, specially on iOS.

There was a similar issue reported, https://github.com/FirebaseExtended/flutterfire/issues/3791 as well.

cc: @helenaford wondering if there's an issue link to track the storage exception bug and if it was fixed, https://github.com/FirebaseExtended/flutterfire/issues/3791#issuecomment-706539690 ? because it seems to be occuring using latest plugin version as above.

@Tom3652 Can you please provide a complete code sample that we can use to verify this issue.

Tom3652 commented 3 years ago

This is the code sample. It happened again 1 time over 10 on a physical device, and 100% on the IOS simulator 12 Pro Max.

You will need the photo_manager package :

code sample ``` void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: FirebaseTest(), ); } } class FirebaseTest extends StatefulWidget { @override _FirebaseTestState createState() => _FirebaseTestState(); } class _FirebaseTestState extends State { List _tasks = []; void onAssetPicked(File file) async { setState(() { UploadTask currentTask = FirebaseStorage.instance .ref() .child("images") .child(file.hashCode.toString()) .putFile(file); _tasks.add(currentTask); }); } @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( actions: [ IconButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => GalleryPage( selectedFileCallback: onAssetPicked))); }, icon: Icon(Icons.add)) ], ), body: ListView.builder( shrinkWrap: true, itemCount: _tasks.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(8.0), child: Center(child: TaskItem(_tasks[index])), ); })); } } class TaskItem extends StatefulWidget { final UploadTask task; TaskItem(this.task); @override _TaskItemState createState() => _TaskItemState(); } class _TaskItemState extends State { double progress = 0; bool success = false; bool error = false; String errorResult = ""; void _onTask() { widget.task.snapshotEvents.listen((event) { setState(() { progress = event.bytesTransferred / event.totalBytes * 100; }); }); widget.task.then((value) { setState(() { success = true; }); }); widget.task.catchError((error) { print("An error has occurred : $error"); setState(() { this.error = true; errorResult = error.toString(); }); }); } @override void initState() { super.initState(); _onTask(); } @override Widget build(BuildContext context) { return success ? Container( child: Text("Photo uploaded with success."), ) : error ? Container( child: Text("Error when upload : $errorResult"), ) : Container( height: 20, child: Text("Task progress : $progress"), ); } } class GalleryPage extends StatefulWidget { final ValueChanged selectedFileCallback; GalleryPage({required this.selectedFileCallback}); @override _GalleryPageState createState() => _GalleryPageState(); } class _GalleryPageState extends State { List assets = []; void _fetchAssets() async { bool granted = await PhotoManager.requestPermission(); if (granted) { final albums = await PhotoManager.getAssetPathList(onlyAll: true); assets = await albums.first.getAssetListRange(start: 0, end: 10); print("Assets found : " + assets.toString()); setState(() { }); } else { print("Re ask permission"); // Ugly, but for the test to not make you rebuild the app if you missed the permission _fetchAssets(); } } @override void initState() { super.initState(); _fetchAssets(); } @override Widget build(BuildContext context) { return Scaffold( body: GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 2, mainAxisSpacing: 2, childAspectRatio: 0.55, ), /*staggeredTileBuilder: (int index) { return StaggeredTile.fit(1); },*/ itemCount: assets.length, physics: BouncingScrollPhysics(), shrinkWrap: true, itemBuilder: (context, index) { return GestureDetector( onTap: () async { File? file = await assets[index].file; if (file != null && file.existsSync()) { print("File exists !"); widget.selectedFileCallback(file); Navigator.pop(context); } else { print("File doesn't exist !"); } }, child: GalleryItem(assets[index])); }, //crossAxisCount: 3, //crossAxisSpacing: 5, //mainAxisSpacing: 5, ), ); } } class GalleryItem extends StatelessWidget { final AssetEntity asset; GalleryItem(this.asset); @override Widget build(BuildContext context) { return asset.type == AssetType.video ? Container() : FutureBuilder( future: asset.thumbDataWithSize(250, 250), builder: (_, snapshot) { final bytes = snapshot.data; if (snapshot.hasError) { return Container(); } // If we have no data, display a spinner if (bytes == null) return Container(); // If there's data, display it as an image return Image.memory(bytes, fit: BoxFit.cover); }, ); } } ```
darshankawar commented 3 years ago

Thanks for the code sample. I used it on latest master and verified on iphone 6s which has 6 full HD (1920x1080) images, but didn't get the issue you mentioned, as everytime, as I got file exists message in the console while uploading. Maybe there's a pattern to replicate which I didn't hit and requires repeating the steps few times, which I did, but maybe not enough.

Screenshot 2021-08-11 at 1 50 36 PM
console log ``` flutter: Assets found : [AssetEntity (id:A05737F9-84E7-4B64-8330-6972F0354CF1/L0/001 , type: AssetType.video), AssetEntity (id:52AC499D-501D-4436-9200-24C3AFC000DC/L0/001 , type: AssetType.image), AssetEntity (id:BBA40F9D-99C3-453C-80FD-1FA08DC45758/L0/001 , type: AssetType.image), AssetEntity (id:3232EBD4-2EA9-468C-AA43-AF8F40CF123D/L0/001 , type: AssetType.image), AssetEntity (id:D13C6351-4A4B-41AE-A112-69110FC33435/L0/001 , type: AssetType.image), AssetEntity (id:EC8AB51C-3001-4352-B799-EFF398CD7D3B/L0/001 , type: AssetType.image), AssetEntity (id:A0B86BC2-480E-4250-A85D-84E4CA8B6463/L0/001 , type: AssetType.image), AssetEntity (id:9B300239-A81E-4F17-9437-4DEF7AE5F003/L0/001 , type: AssetType.image), AssetEntity (id:08E2C1D1-A574-4CB1-9FAD-D9E59CA32557/L0/001 , type: AssetType.image), AssetEntity (id:9683F56A-E129-43B5-8125-321A6E445257/L0/001 , type: AssetType.video)] flutter: File exists ! BackgroundSession <2D044520-B1E0-467B-9BF4-E18304B70986> connection to background transfer daemon invalidated flutter: Assets found : [AssetEntity (id:A05737F9-84E7-4B64-8330-6972F0354CF1/L0/001 , type: AssetType.video), AssetEntity (id:52AC499D-501D-4436-9200-24C3AFC000DC/L0/001 , type: AssetType.image), AssetEntity (id:BBA40F9D-99C3-453C-80FD-1FA08DC45758/L0/001 , type: AssetType.image), AssetEntity (id:3232EBD4-2EA9-468C-AA43-AF8F40CF123D/L0/001 , type: AssetType.image), AssetEntity (id:D13C6351-4A4B-41AE-A112-69110FC33435/L0/001 , type: AssetType.image), AssetEntity (id:EC8AB51C-3001-4352-B799-EFF398CD7D3B/L0/001 , type: AssetType.image), AssetEntity (id:A0B86BC2-480E-4250-A85D-84E4CA8B6463/L0/001 , type: AssetType.image), AssetEntity (id:9B300239-A81E-4F17-9437-4DEF7AE5F003/L0/001 , type: AssetType.image), AssetEntity (id:08E2C1D1-A574-4CB1-9FAD-D9E59CA32557/L0/001 , type: AssetType.image), AssetEntity (id:9683F56A-E129-43B5-8125-321A6E445257/L0/001 , type: AssetType.video)] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service Could not signal service com.apple.WebKit.Networking: 113: Could not find specified service flutter: File exists ! BackgroundSession connection to background transfer daemon invalidated flutter: Assets found : [AssetEntity (id:A05737F9-84E7-4B64-8330-6972F0354CF1/L0/001 , type: AssetType.video), AssetEntity (id:52AC499D-501D-4436-9200-24C3AFC000DC/L0/001 , type: AssetType.image), AssetEntity (id:BBA40F9D-99C3-453C-80FD-1FA08DC45758/L0/001 , type: AssetType.image), AssetEntity (id:3232EBD4-2EA9-468C-AA43-AF8F40CF123D/L0/001 , type: AssetType.image), AssetEntity (id:D13C6351-4A4B-41AE-A112-69110FC33435/L0/001 , type: AssetType.image), AssetEntity (id:EC8AB51C-3001-4352-B799-EFF398CD7D3B/L0/001 , type: AssetType.image), AssetEntity (id:A0B86BC2-480E-4250-A85D-84E4CA8B6463/L0/001 , type: AssetType.image), AssetEntity (id:9B300239-A81E-4F17-9437-4DEF7AE5F003/L0/001 , type: AssetType.image), AssetEntity (id:08E2C1D1-A574-4CB1-9FAD-D9E59CA32557/L0/001 , type: AssetType.image), AssetEntity (id:9683F56A-E129-43B5-8125-321A6E445257/L0/001 , type: AssetType.video)] flutter: File exists ! ```
flutter doctor -v ``` [✓] Flutter (Channel master, 2.5.0-6.0.pre.45, on Mac OS X 10.15.4 19E2269 darwin-x64, locale en-GB) • Flutter version 2.5.0-6.0.pre.45 at /Users/dhs/documents/fluttersdk/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision b08366ce7b (3 hours ago), 2021-08-10 22:22:08 -0700 • Engine revision 4fef55db10 • Dart version 2.14.0 (build 2.14.0-385.0.dev) [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 12.3, Build version 12C33 • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.58.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (4 available) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 92.0.4515.131 ```

I am going to keep this open for further insights from the team, as I think it has most likely to do with a bug in storage exceptions on iOS. https://github.com/FirebaseExtended/flutterfire/issues/6776#issuecomment-895789901

Tom3652 commented 3 years ago

Thanks for keeping this open.

I have noticed 2 more things since i have made this sample app :

I have a quite poor internet connection so it's good for tests, but is there any timeout on the UploadTask ?

Here are the results to show the first point :

Capture d’écran 2021-08-11 à 11 10 35

The UploadTask is at 100% above (you can see the VM time).

Capture d’écran 2021-08-11 à 11 11 06

Here are my results to show the second point :

Capture d’écran 2021-08-11 à 11 01 12

The UploadTask is at 100% again.

Capture d’écran 2021-08-11 à 11 02 50

And it's restarting.

Capture d’écran 2021-08-11 à 11 01 45

russellwheatley commented 3 years ago

@Tom3652 please provide a full code sample for me to copy and paste (i.e. including imports).

Tom3652 commented 3 years ago

@russellwheatley it's the same as i provided above. The photo_manager version is : photo_manager: ^1.3.1 And all firebase are latest versions. I give you everything back with imports :

import 'dart:io';
import 'dart:typed_data';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:photo_manager/photo_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: FirebaseTest(),
    );
  }
}

class FirebaseTest extends StatefulWidget {
  @override
  _FirebaseTestState createState() => _FirebaseTestState();
}

class _FirebaseTestState extends State<FirebaseTest> {
  List<UploadTask> _tasks = [];

  void onAssetPicked(File file) async {
    setState(() {
      UploadTask currentTask = FirebaseStorage.instance
          .ref()
          .child("images")
          .child(file.hashCode.toString())
          .putFile(file);
      _tasks.add(currentTask);
    });
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          actions: [
            IconButton(
                onPressed: () {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => GalleryPage(
                              selectedFileCallback: onAssetPicked)));
                },
                icon: Icon(Icons.add))
          ],
        ),
        body: ListView.builder(
            shrinkWrap: true,
            itemCount: _tasks.length,
            itemBuilder: (context, index) {
              return Padding(
                padding: const EdgeInsets.all(8.0),
                child: Center(child: TaskItem(_tasks[index])),
              );
            }));
  }
}

class TaskItem extends StatefulWidget {

  final UploadTask task;
  TaskItem(this.task);

  @override
  _TaskItemState createState() => _TaskItemState();
}

class _TaskItemState extends State<TaskItem> {

  double progress = 0;
  bool success = false;
  bool error = false;
  String errorResult = "";

  void _onTask() {
    widget.task.snapshotEvents.listen((event) {
      setState(() {
        progress = event.bytesTransferred / event.totalBytes * 100;
      });
    });
    widget.task.then((value) {
      setState(() {
        success = true;
      });
    });
    widget.task.catchError((error) {
      print("An error has occurred : $error");
      setState(() {
        this.error = true;
        errorResult = error.toString();
      });
    });
  }

  @override
  void initState() {
    super.initState();
    _onTask();
  }

  @override
  Widget build(BuildContext context) {
    return success
        ? Container(
            child: Text("Photo uploaded with success."),
          ) : error
            ? Container(
                child: Text("Error when upload : $errorResult"),
              ) : Container(
                height: 20,
                child: Text("Task progress : $progress"),
              );
  }
}

class GalleryPage extends StatefulWidget {

  final ValueChanged<File> selectedFileCallback;
  GalleryPage({required this.selectedFileCallback});

  @override
  _GalleryPageState createState() => _GalleryPageState();
}

class _GalleryPageState extends State<GalleryPage> {

  List<AssetEntity> assets = [];

  void _fetchAssets() async {
    bool granted = await PhotoManager.requestPermission();
    if (granted) {
      final albums = await PhotoManager.getAssetPathList(onlyAll: true);
      assets = await albums.first.getAssetListRange(start: 0, end: 10);
      print("Assets found : " + assets.toString());
      setState(() {

      });
    } else {
      print("Re ask permission");
      // Ugly, but for the test to not make you rebuild the app if you missed the permission
      _fetchAssets();
    }
  }

  @override
  void initState() {
    super.initState();
    _fetchAssets();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          crossAxisSpacing: 2,
          mainAxisSpacing: 2,
          childAspectRatio: 0.55,
        ),
        /*staggeredTileBuilder: (int index) {
              return StaggeredTile.fit(1);
            },*/
        itemCount: assets.length,
        physics: BouncingScrollPhysics(),
        shrinkWrap: true,
        itemBuilder: (context, index) {
          return GestureDetector(
              onTap: () async {
                File? file = await assets[index].file;
                if (file != null && file.existsSync()) {
                  print("File exists !");
                  widget.selectedFileCallback(file);
                  Navigator.pop(context);
                } else {
                  print("File doesn't exist !");
                }
              },
              child: GalleryItem(assets[index]));
        },
        //crossAxisCount: 3,
        //crossAxisSpacing: 5,
        //mainAxisSpacing: 5,
      ),
    );
  }
}

class GalleryItem extends StatelessWidget {
  final AssetEntity asset;
  GalleryItem(this.asset);

  @override
  Widget build(BuildContext context) {
    return
      asset.type == AssetType.video ? Container() :
      FutureBuilder<Uint8List?>(
      future: asset.thumbDataWithSize(250, 250),
      builder: (_, snapshot) {
        final bytes = snapshot.data;
        if (snapshot.hasError) {
          return Container();
        }
        // If we have no data, display a spinner
        if (bytes == null) return Container();
        // If there's data, display it as an image
        return Image.memory(bytes, fit: BoxFit.cover);
      },
    );
  }
}
russellwheatley commented 3 years ago

@Tom3652 I tried using your complete code snippet on my iphone 12 14.4 simulator, and as soon as I pressed the button to upload, the connection was lost.

https://user-images.githubusercontent.com/16018629/129866807-edb8e0e9-f2f1-4cdd-913d-8e2e21359222.mp4

Tom3652 commented 3 years ago

Hi @russellwheatley, i have improved the code despite it was working in my case. I believe this was due to a permission conflict.

I have made a central button and delay the permission request in initState(). I have tested it on iphone 12 in IOS 14.5. Please tell me if the following works for you :

import 'dart:io';
import 'dart:typed_data';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:photo_manager/photo_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: FirebaseTest(),
    );
  }
}

class FirebaseTest extends StatefulWidget {
  @override
  _FirebaseTestState createState() => _FirebaseTestState();
}

class _FirebaseTestState extends State<FirebaseTest> {
  List<UploadTask> _tasks = [];

  void onAssetPicked(File file) async {
    setState(() {
      UploadTask currentTask = FirebaseStorage.instance
          .ref()
          .child("images")
          .child(file.hashCode.toString())
          .putFile(file);
      _tasks.add(currentTask);
    });
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          actions: [
            IconButton(
                onPressed: () {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => GalleryPage(
                              selectedFileCallback: onAssetPicked)));
                },
                icon: Icon(Icons.add))
          ],
        ),
        body: ListView.builder(
            shrinkWrap: true,
            itemCount: _tasks.length,
            itemBuilder: (context, index) {
              return Padding(
                padding: const EdgeInsets.all(8.0),
                child: Center(child: TaskItem(_tasks[index])),
              );
            }));
  }
}

class TaskItem extends StatefulWidget {
  final UploadTask task;

  TaskItem(this.task);

  @override
  _TaskItemState createState() => _TaskItemState();
}

class _TaskItemState extends State<TaskItem> {
  double progress = 0;
  bool success = false;
  bool error = false;
  String errorResult = "";

  void _onTask() {
    widget.task.snapshotEvents.listen((event) {
      setState(() {
        progress = event.bytesTransferred / event.totalBytes * 100;
      });
    });
    widget.task.then((value) {
      setState(() {
        success = true;
      });
    });
    widget.task.catchError((error) {
      print("An error has occurred : $error");
      setState(() {
        this.error = true;
        errorResult = error.toString();
      });
    });
  }

  @override
  void initState() {
    super.initState();
    _onTask();
  }

  @override
  Widget build(BuildContext context) {
    return success
        ? Container(
      child: Text("Photo uploaded with success."),
    )
        : error
        ? Container(
      child: Text("Error when upload : $errorResult"),
    )
        : Container(
      height: 20,
      child: Text("Task progress : $progress"),
    );
  }
}

class GalleryPage extends StatefulWidget {
  final ValueChanged<File> selectedFileCallback;

  GalleryPage({required this.selectedFileCallback});

  @override
  _GalleryPageState createState() => _GalleryPageState();
}

class _GalleryPageState extends State<GalleryPage> {
  List<AssetEntity> assets = [];

  bool granted = false;

  void _fetchAssets() async {
    granted = await PhotoManager.requestPermission();
    if (granted) {
      final albums = await PhotoManager.getAssetPathList(onlyAll: true);
      assets = await albums.first.getAssetListRange(start: 0, end: 10);
      print("Assets found : " + assets.toString());
      setState(() {});
    }
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      _fetchAssets();
    });
  }

  @override
  Widget build(BuildContext context) {
    return !granted
        ? Scaffold(
      body: Container(
          child: Center(
              child: GestureDetector(
                child: Container(child: Center(child: Text("Ask permissions", textAlign: TextAlign.center)),
                    width: 100, height: 100, color: Colors.blue),
                onTap: () async {
                  print("Requesting permissions again");
                  var result = await PhotoManager.requestPermissionExtend();
                  if (result.isAuth) {
                    setState(() {
                      granted = true;
                    });
                  }
                  else {
                    print("Can't do anything");
                    PhotoManager.openSetting();
                  }
                },
              )
          )
      ),
    )
        : Scaffold(
      body: GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          crossAxisSpacing: 2,
          mainAxisSpacing: 2,
          childAspectRatio: 0.55,
        ),
        /*staggeredTileBuilder: (int index) {
              return StaggeredTile.fit(1);
            },*/
        itemCount: assets.length,
        physics: BouncingScrollPhysics(),
        shrinkWrap: true,
        itemBuilder: (context, index) {
          return GestureDetector(
              onTap: () async {
                File? file = await assets[index].file;
                if (file != null && file.existsSync()) {
                  print("File exists !");
                  widget.selectedFileCallback(file);
                  Navigator.pop(context);
                } else {
                  print("File doesn't exist !");
                }
              },
              child: GalleryItem(assets[index]));
        },
        //crossAxisCount: 3,
        //crossAxisSpacing: 5,
        //mainAxisSpacing: 5,
      ),
    );
  }
}

class GalleryItem extends StatelessWidget {
  final AssetEntity asset;

  GalleryItem(this.asset);

  @override
  Widget build(BuildContext context) {
    return asset.type == AssetType.video
        ? Container()
        : FutureBuilder<Uint8List?>(
      future: asset.thumbDataWithSize(250, 250),
      builder: (_, snapshot) {
        final bytes = snapshot.data;
        if (snapshot.hasError) {
          return Container();
        }
        // If we have no data, display a spinner
        if (bytes == null) return Container();
        // If there's data, display it as an image
        return Image.memory(bytes, fit: BoxFit.cover);
      },
    );
  }
}
Tom3652 commented 3 years ago

It happened today on my real device with a complementary information. When i click on the error link it gives me :

Invalid request.  X-Goog-Upload-Command header is missing.

I have checked this answer but i am not uploading an UriSession.

Tom3652 commented 3 years ago

I happened again twice and this time on my Android physical device. Not sure i can reproduce this 100% like on IOS but Crashlytics caught the error (custom trace i have logged, this is not a crash)

Tom3652 commented 3 years ago

Here is the stack trace for Android i have got few minutes ago :

D/UploadTask(15225): Increasing chunk size to 524288
W/NetworkRequest(15225): No App Check token for request.
W/NetworkRequest(15225): error sending network request POST https://firebasestorage.googleapis.com/v0/b/project_id.appspot.com/o?name=posts&uploadType=resumable&upload_id=ADPycdsFVeV0LkobTufjs-TKLV9VLPK5R9rdBDzn8egNALL0D1_mUa2Dzl4xG7tCj2oPfTK35YIV-S2bS96VP2QQJ70&upload_protocol=resumable
D/UploadTask(15225): Resetting chunk size to 262144
W/ExponenentialBackoff(15225): network unavailable, sleeping.
W/ExponenentialBackoff(15225): network unavailable, sleeping.
I/DpmTcmClient(15225): RegisterTcmMonitor from: $Proxy0
W/NetworkRequest(15225): No App Check token for request.
E/StorageException(15225): StorageException has occurred.
E/StorageException(15225): An unknown error occurred, please check the HTTP result code and inner exception for server response.
E/StorageException(15225):  Code: -13000 HttpResult: 200
E/StorageException(15225): The server has terminated the upload session
E/StorageException(15225): java.io.IOException: The server has terminated the upload session
E/StorageException(15225):  at com.google.firebase.storage.UploadTask.recoverStatus(UploadTask.java:373)
E/StorageException(15225):  at com.google.firebase.storage.UploadTask.shouldContinue(UploadTask.java:325)
E/StorageException(15225):  at com.google.firebase.storage.UploadTask.run(UploadTask.java:232)
E/StorageException(15225):  at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072)
E/StorageException(15225):  at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2)
E/StorageException(15225):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/StorageException(15225):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/StorageException(15225):  at java.lang.Thread.run(Thread.java:919)
E/StorageException(15225): StorageException has occurred.
E/StorageException(15225): An unknown error occurred, please check the HTTP result code and inner exception for server response.
E/StorageException(15225):  Code: -13000 HttpResult: 200
E/StorageException(15225): The server has terminated the upload session
E/StorageException(15225): java.io.IOException: The server has terminated the upload session
E/StorageException(15225):  at com.google.firebase.storage.UploadTask.recoverStatus(UploadTask.java:373)
E/StorageException(15225):  at com.google.firebase.storage.UploadTask.shouldContinue(UploadTask.java:325)
E/StorageException(15225):  at com.google.firebase.storage.UploadTask.run(UploadTask.java:232)
E/StorageException(15225):  at com.google.firebase.storage.StorageTask.lambda$getRunnable$7$StorageTask(StorageTask.java:1072)
E/StorageException(15225):  at com.google.firebase.storage.-$$Lambda$StorageTask$q9YBoR_A8LB-JxTCx8JRQvabaZs.run(Unknown Source:2)
E/StorageException(15225):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/StorageException(15225):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/StorageException(15225):  at java.lang.Thread.run(Thread.java:919)

I have changed the URL to not show publicly my paths and IDs but if i click on the link i see the same message as my above comment : Capture d’écran 2021-09-25 à 17 34 31

The use case was simply that i lost network connection and got it back almost right after.

Tom3652 commented 3 years ago

Hello @russellwheatley, will this be fixed soon ?

It happens to all of my users in beta test on various devices (iphone XR, iphone 11 pro max, Oppo (android 10), iphone 12 pro max, iphone XS max, sony xperia android 11)

I have to switch to S3 if i can't use it in production unfortunately...

Darok13 commented 3 years ago

I am seeing the same kind of error when uploading files randomly, not even multiple at the same time :

flutter: Progress: 96.93651831008722 %
flutter: Task state: TaskState.running
flutter: Progress: 100.0 %
Task <560B02E0-A5FA-4B04-938D-FF2A00692AE7>.<1> finished with error [-1017] Error Domain=NSURLErrorDomain Code=-1017 “cannot parse response” UserInfo={_kCFStreamErrorCodeKey=-1, _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundUploadTask <560B02E0-A5FA-4B04-938D-FF2A00692AE7>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    “BackgroundUploadTask <560B02E0-A5FA-4B04-938D-FF2A00692AE7>.<1>“,
    “LocalUploadTask <560B02E0-A5FA-4B04-938D-FF2A00692AE7>.<1>”
), NSLocalizedDescription=cannot parse response, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://firebasestorage.googleapis.com/v0/b/myprojectid.appspot.com/o/users%2FO3vfL3AHF2XZrX3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d?uploadType=resumable&name=users%2FO3vfL3AHF2XZrX3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d&upload_id=ADPycdtkkp6aAFHhsBww6bhxooPBGyzW0Ndo27iNnY_0pTUevJ8usKIunVXAHyQqFitgjjnFXfxXLS3wiiO7AlvIqEQ&upload_protocol=resumable, NSErrorFailingURLKey=https://firebasestorage.googleapis.com/v0/b/myprojectid.appspot.com/o/users%2FO3vfL3AHF2XZrX3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d?uploadType=resumable&name=users%2FO3vfL3AHF2XZrX3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d&upload_id=ADPycdtkkp6aAFHhsBww6bhxooPBGyzW0Ndo27iNnY_0pTUevJ8usKIunVXAHyQqFitgjjnFXfxXLS3wiiO7AlvIqEQ&upload_protocol=resumable}
GTMSessionFetcher invoking fetch callbacks, data (null), error Error Domain=NSURLErrorDomain Code=-1017 “cannot parse response” UserInfo={_kCFStreamErrorCodeKey=-1, _NSURLErrorFailingURLSessionTaskErrorKey=BackgroundUploadTask <560B02E0-A5FA-4B04-938D-FF2A00692AE7>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    “BackgroundUploadTask <560B02E0-A5FA-4B04-938D-FF2A00692AE7>.<1>“,
    “LocalUploadTask <560B02E0-A5FA-4B04-938D-FF2A00692AE7>.<1>”
), NSLocalizedDescription=cannot parse response, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=https://firebasestorage.googleapis.com/v0/b/myprojectid.appspot.com/o/users%2FO3vfL3AHF2XZrX3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d?uploadType=resumable&name=users%2FO3vfL3AHF2XZrz3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d&upload_id=ADPycdtkkp6aAFHhsBww6bhxooPBGyzW0Ndo27iNnY_0pTUevJ8usKIunVXAHyQqFitgjjnFXfxXLS3wiiO7AlvIqEQ&upload_protocol=resumable, NSErrorFailingURLKey=https://firebasestorage.googleapis.com/v0/b/myprojectid.appspot.com/o/users%2FO3vfL3AHF2XZrX3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d?uploadType=resumable&name=users%2FO3vfL3AHF2XZrz3BKh8VQVOsbmz1%2Fcontent%2F86f125a1-367f-11ec-a005-1dff5d6aaf6d&upload_id=ADPycdtkkp6aAFHhsBww6bhxooPBGyzW0Ndo27iNnY_0pTUevJ8usKIunVXAHyQqFitgjjnFXfxXLS3wiiO7AlvIqEQ&upload_protocol=resumable}
BackgroundSession <7D197581-6F73-4E13-A984-67E03DAE5D56> connection to background transfer daemon invalidated
flutter: Task state: TaskState.running
flutter: Progress: 100.0 %
flutter: ----------------FIREBASE CRASHLYTICS----------------
flutter: [firebase_storage/unknown] An unknown error occurred, please check the server response.
flutter:
flutter: ----------------------------------------------------
flutter: error : [firebase_storage/unknown] An unknown error occurred, please check the server response.

It seems to happen only when the progress is 100% as you mentioned @Tom3652 : "The UploadTask goes in error right after the progress is 100."
But i have no automatic restart, only this weird failure Is there any logs or more details to be able to read ? I would like to check the internal server error actually, what does it say ?

I thought this plugin was production-ready and stable but i am new to firebase storage and unable to use it :( i actually have the same error using your code sample

Tom3652 commented 3 years ago

I started to believe that i was the only one with this issue... Thanks for sharing @Darok13

In the meantime i have already implemented upload sessions with AWS S3 which works fine.
It also confirms that the issue is not from my code (i also started to believe that despite the reproductible sample code). If not everyone is able to reproduce this, what would be different ? Connection state ?

But S3 is working fine with this connection : Capture d’écran 2021-10-26 à 19 47 34

This anyway doesn't explain why the upload is failing at the end. Let's suppose it's a connectivity issue, then it would tell that Firebase is blocking any upload under a specific bandwidth or something...

Edit : I realize that all of my users (10 for now) can't always have connection issues. Of course they can, but not that often... So the connectivity lead is less relevant actually but with this bandwidth it's always failing.

Darok13 commented 3 years ago

I have found this #3791 which is closed but the bug is still happening. It tells in this case that the issue is actually something else but the message is unclear.

In my case i have no permission denied underlying, so i will try to downgrade the plugin and see if this works normally.

Darok13 commented 3 years ago

I have found what was the issue. This is actually a bug but when i was uploading multiple task at the same time it was crashing like this.

Now i am simply uploading tasks one by one instead of parallel, with a queued system. The error is really not easy to understand i had to refactor a lot of things to test this.

Hope this helps.

Tom3652 commented 3 years ago

You are right this works when uploading files one by one i have tested it.
However this issue is about multiple files at the same time.

It would be really nice to have a better error than unknown in case of multiple files simultaneously or at least state it in the documentation.

Tom3652 commented 2 years ago

This error as the title said, was to handle the null in the catch error, and not to fix the underlying SDK issue that causes an unknown error, here is the follow up #7706 for the unknown error.

This one was fixed as i don't get this message anymore, only the unknown error.