System.ObjectDisposedException: 'Cannot access a closed Stream on .net 8 maui android
Description
When images are loaded from a memorystream on to a page, when going back via the backbutton on an android device a fatal error occurs. But not always, but often.
Please try the project in the repository, It is based on @jfversluis MauiBase64ImageSample on git.
Steps to Reproduce
- Create a new maui navigationpage app
- create a contentview that holds the image
- create a contentpage that holds several views with image
- create several pages from the mainpage
- use the backbutton to close the pages
- observe the error
Link to public reproduction project repository
Version with bug
8.0.3
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
Android, Windows
Affected platform versions
No response
Did you find any workaround?
Cache the files, see project inthe repository
Relevant log output
**System.ObjectDisposedException:** 'Cannot access a closed Stream.'
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.ObjectDisposedException: Cannot access a closed Stream.
[mono-rt] at System.IO.MemoryStream.EnsureNotClosed()
[mono-rt] at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
[mono-rt] at Android.Runtime.InputStreamAdapter.Read(Byte[] bytes, Int32 offset, Int32 length) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/InputStreamAdapter.cs:line 38
[mono-rt] at Java.IO.InputStream.n_Read_arrayBII(IntPtr jnienv, IntPtr native__this, IntPtr native_b, Int32 off, Int32 len) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net7.0/android-33/mcw/Java.IO.InputStream.cs:line 264
[mono-rt] at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_I(_JniMarshal_PPLII_I callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, Int32 p1, Int32 p2) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 264
[HostConnection] createUnique: call
[HostConnection] HostConnection::get() New Host Connection established 0x7c0ff54aff50, tid 31493
[HostConnection] HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_vulkan_queue_submit_with_commands ANDROID_EMU_sync_buffer_data ANDROID_EMU_vulkan_async_qsri ANDROID_EMU_read_color_buffer_dma GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0
We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.
Upgraded the github project to .net 8
Windows machine also crashes on 10 pages or more in the sample project. Workaround added in the repo: caching files and using the filenames is working.
Verified this on Visual Studio Enterprise 17.9.0 Preview 2(8.0.3). Repro on Android 14.0-API34 and Windows 11 with below Project: MauiBase64ImageSample.zip
@tariksaibi
We are having the same issue. After I load the image from memory stream and open a new page and navigate to back, I receive System.ObjectDisposedException on Android. This issue is preventing us to go live. When will we have a fix for this?
Same issue here, why is this added to the backlog? is there at least some sort of workaround?
I work around it by clearing the android imagecache:
var imageManagerDiskCache = Path.Combine(FileSystem.CacheDirectory, "image_manager_disk_cache");
if (Directory.Exists(imageManagerDiskCache))
{
foreach (var imageCacheFile in Directory.EnumerateFiles(imageManagerDiskCache))
{
File.Delete(imageCacheFile);
}
}
@Eves101 thanks for the snippet, how often do you run this? do you use a timer or something?
I call it when i cache or delete a file, soo fairly often... :(
Hi @Eves101 Do you have a sample on how to apply your workaround?
Not exactly sure either, I do not cache any images, mine usually loads from from a local SQLITE db, or just in memory, like a user avatar.
@naaeef I take this approach:
- get an image from api in a stream
- empty the android cache
- save the image to the app data folder/yourfoldername/ ( with a filename like: avatar.jpg)
- assign the filename to the imagesource
I don't get how this issue hasn't been fixed for 4 months. Saving the image may sound as workaround but it is basically a whole different approach people use to avoid this issue.
@jonathanpeppers thoughts?
This feels like "MAUI doesn't handle cancellation", right?
Looking at the code:
https://github.com/dotnet/maui/blob/68f6e4be973d60f3ab376dcdb0025645a9d4a6fc/src/Core/src/ImageSources/StreamImageSourceService/StreamImageSourceService.Android.cs#L28-L32
If you navigated away from the page, I don't see what would cancel this gracefully.
Can someone comment what method in the sample is the problematic one? Which one of these?
- https://github.com/Eves101/MauiBase64ImageImageStreamTest/blob/8925d75bcbcd08892219d96f0540e7cec7f6c5f2/MauiBase64ImageSample/Base64ImageProvider.cs#L12
- https://github.com/Eves101/MauiBase64ImageImageStreamTest/blob/8925d75bcbcd08892219d96f0540e7cec7f6c5f2/MauiBase64ImageSample/Base64ImageProvider.cs#L32
👀 seems to happen when scrolling back up on CollectionView after scrolling down through items when items have ImageSource value set i.e. ImageSource.FromStream(() => copyStream)
The offending code seems to be:
MemoryStream copyStream = new();
await memoryStream.CopyToAsync(copyStream).ConfigureAwait(true);
copyStream.Position = 0;
viewModels.ImageSource = ImageSource.FromStream(() => copyStream);
Also seeing this issue in our production android application. The rate is low but impact is high as the entire Android app crashes as a result of this issue. We do not see this issue on iOS, only on Android.
Also facing the same issue. CV with images
We started having this issue after upgrading our app to .net 8 just before giving it to testers. It was working fine with .net 7. Our job was converting an existing production xamarin app to maui. I think it was like 10-11 months ago. This issue was the biggest reason the whole project was cancelled and the maui app didn't go live. I am not exaggerating. It was decided it would take too much effort to keep maintaining maui apps.
This is still a big problem, it might as well be on par with https://github.com/dotnet/maui/issues/25224 which we also suffer from, for this issue though you cannot scroll down more then 10 items in a CollectionView with images until the app crashes.
App also crashes on simple page navigation. What is the update on this ticket??? This is blocking our ability to release a stable production version.
To update everyone we made a slight adjustment with the following change and we dont't seem to get this crash occuring as frequent, if at all now. Someone else can confirm.
- Create a Copy of the Stream: • A MemoryStream is created to copy the contents of the original stream. • The position of the copied stream is reset to the beginning.
- Use the Copied Stream: • The copied stream is used to create the ImageSource by converting it to a byte array and then creating a new MemoryStream from the byte array.
Stream? imageStream = await fileResult.OpenReadAsync().ConfigureAwait(true);
if (imageStream is not null)
{
// Create a copy of the stream to avoid disposing issues
MemoryStream copyStream = new();
await imageStream.CopyToAsync(copyStream).ConfigureAwait(true);
copyStream.Position = 0; // Reset position to the beginning
// Use the copied stream to create the ImageSource
ImageSource = ImageSource.FromStream(() => new MemoryStream(copyStream.ToArray())); // <=== Include a new MemoryStream
}
To update everyone we made a slight adjustment with the following change and we dont't seem to get this crash occuring as frequent, if at all now. Someone else can confirm.
- Create a Copy of the Stream: • A MemoryStream is created to copy the contents of the original stream. • The position of the copied stream is reset to the beginning.
- Use the Copied Stream: • The copied stream is used to create the ImageSource by converting it to a byte array and then creating a new MemoryStream from the byte array.
Stream? imageStream = await fileResult.OpenReadAsync().ConfigureAwait(true); if (imageStream is not null) { // Create a copy of the stream to avoid disposing issues MemoryStream copyStream = new(); await imageStream.CopyToAsync(copyStream).ConfigureAwait(true); copyStream.Position = 0; // Reset position to the beginning
// Use the copied stream to create the ImageSource ImageSource = ImageSource.FromStream(() => new MemoryStream(copyStream.ToArray())); // <=== Include a new MemoryStream}
@LeoJHarris This has fixed it for me, thanks! Shame we have to use three memory streams instead of one, but it's better than the app crashing that's for sure. Hopefully MAUI team will address the root cause in future.
Can still reproduce the crash using the sample above on net/maui 9.0
Adding another MemoryStream did not help.
Also I am getting similar error. My codes which I use as following.
var aresult = await MediaPicker.CapturePhotoAsync(new MediaPickerOptions() { Title = title });
if (aresult != null)
{
var newFile = Path.Combine(FileSystem.CacheDirectory, aresult.FileName);
using (var stream = await aresult.OpenReadAsync())
using (var newStream = File.OpenWrite(newFile))
{
await stream.CopyToAsync(newStream);
}
Error
**System.ObjectDisposedException:** 'Cannot access a closed Stream.'
Project Specs
<TargetFrameworks>net9.0-android;net9.0-ios</TargetFrameworks>
<MauiVersion>9.0.22</MauiVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
Android Manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
Time Device Name Type PID Tag Message
01-11 12:43:19.404 pixel_5_-_api_33 Error 20471 mono-rt [ERROR] FATAL UNHANDLED EXCEPTION: System.ObjectDisposedException: Cannot access a closed Stream.
at System.IO.MemoryStream.EnsureNotClosed()
at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at Android.Runtime.InputStreamAdapter.Read(Byte[] bytes, Int32 offset, Int32 length) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/InputStreamAdapter.cs:line 38
at Java.IO.InputStream.n_Read_arrayBII(IntPtr jnienv, IntPtr native__this, IntPtr native_b, Int32 off, Int32 len) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Java.IO.InputStream.cs:line 229
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_I(_JniMarshal_PPLII_I callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, Int32 p1, Int32 p2) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 275
I'm facing this bug and getting many problems to finish an .net maui application only in cause of this. Nothing said from Microsoft .net Maui team to clear this situation? Thanks all.
This is still an issue in .NET 9.0.30
I am having same issue. Using latest .NET 9
Is there any update on this?