glide icon indicating copy to clipboard operation
glide copied to clipboard

Image Loading Failure: Mark has been invalidated Error when load png file which is bigger than 5MB, without diskCache

Open Teddyleee opened this issue 3 years ago • 2 comments

Glide Version:

4.14.2

Integration libraries:

com.github.bumptech.glide:Volley:4.14.2

Device/Android Version:

API 31

Issue details / Repro steps / Use case background:

It's similar issue with 4517 (https://github.com/bumptech/glide/issues/4517)

When you try to load 5MB png file(which size bigger than max buffer size in recycleablebufferedinputStream in Glide(5MB)) without Data Cache(Disk only cache resource), you fail load image

The cause of this problem is. when you try to get Orientation(in downsampler.java, 330 Line). it use ExifInterface and when ExifInterface Initialize, it read InputStream. And then the inputStream gets wrong.

before get Orientation, it can decode InputStream, image

but It can't after ExifInterface read the inputStream.

If you use Data(not resource) Cache after fail all try to load image using inputStream, then it try to load image using file cached on disk(not using inputStream) So. it load image successfully. (In this case it doesn't use stream)

I think when the stream size is bigger than 5 MB it should return default Orientation -1(if it use ExifInterface)

The Error message is

class com.bumptech.glide.load.engine.GlideException: Failed to load resource
    There were 4 root causes:
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
     call GlideException#logRootCauses(String) for more detail
      Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{ByteArrayInputStream->Object->Drawable}, REMOTE
    There were 4 root causes:
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
     call GlideException#logRootCauses(String) for more detail
        Cause (1 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ByteArrayInputStream->Drawable->Drawable}
    There was 1 root cause:
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
     call GlideException#logRootCauses(String) for more detail
          Cause (1 of 1): class com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException: Mark has been invalidated, pos: 104557 markLimit: 5242880
        Cause (2 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ByteArrayInputStream->GifDrawable->Drawable}
    There was 1 root cause:
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
     call GlideException#logRootCauses(String) for more detail
          Cause (1 of 1): class com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException: Mark has been invalidated, pos: 104557 markLimit: 5242880
        Cause (3 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ByteArrayInputStream->Bitmap->BitmapDrawable}
    There was 1 root cause:
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
     call GlideException#logRootCauses(String) for more detail
          Cause (1 of 1): class com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException: Mark has been invalidated, pos: 104557 markLimit: 5242880
        Cause (4 of 4): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{ByteArrayInputStream->BitmapDrawable->Drawable}
    There was 1 root cause:
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
     call GlideException#logRootCauses(String) for more detail
          Cause (1 of 1): class com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException: Mark has been invalidated, pos: 104557 markLimit: 5242880
2022-11-08 19:58:19.193 12813-12813/net.bucketplace E/ImgBoxUi: Load Failed : com.bumptech.glide.load.engine.GlideException: Failed to load resource
    There were 4 root causes:
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
    com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 104557 markLimit: 5242880)
     call GlideException#logRootCauses(String) for more detail

Teddyleee avatar Nov 08 '22 11:11 Teddyleee

Things that make this hard:

  1. The image can be arbitrarily large, so increasing the buffer size from 5mb just trades off the type/% of images will fail against the risk of OOM/excessive memory use
  2. The image can be decoded without the orientation, but then it turns a loud/obvious failure into an incorrectly rotated image some % of the time. That's hard to debug and hard to fix if it's cached.
  3. I believe that this failure only occurs when the image is not available on disk and data disk caching is disabled. If the data disk cache is enabled, the image should be decoded successfully via the ParcleFileDescriptor path.

We could change either #1 or #2, but at the cost of less obvious failures. I'm inclined to think the best way to handle these images is to go through the disk cache.

sjudd avatar Nov 13 '22 20:11 sjudd

In our app this seems to happen even with a disk cache strategy of DiskCacheStrategy.ALL. So large PNG images cannot be handled at all. The root cause is:

class com.bumptech.glide.load.engine.GlideException: Failed to load resource
There was 1 root cause:
com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 4113446 markLimit: 5242880)
 call GlideException#logRootCauses(String) for more detail
  Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Failed LoadPath{FileInputStream->Bitmap->Bitmap}, LOCAL
There was 1 root cause:
com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 4113446 markLimit: 5242880)
 call GlideException#logRootCauses(String) for more detail
    Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Failed DecodePath{FileInputStream->Bitmap->Bitmap}
There was 1 root cause:
com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException(Mark has been invalidated, pos: 4113446 markLimit: 5242880)
 call GlideException#logRootCauses(String) for more detail
      Cause (1 of 1): class com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException: Mark has been invalidated, pos: 4113446 markLimit: 5242880

com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream$InvalidMarkException: Mark has been invalidated, pos: 4113446 markLimit: 5242880
	at com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream.reset(RecyclableBufferedInputStream.java:344)
	at com.bumptech.glide.load.ImageHeaderParserUtils$5.getOrientationAndRewind(ImageHeaderParserUtils.java:184)
	at com.bumptech.glide.load.ImageHeaderParserUtils.getOrientationInternal(ImageHeaderParserUtils.java:229)
	at com.bumptech.glide.load.ImageHeaderParserUtils.getOrientation(ImageHeaderParserUtils.java:176)
	at com.bumptech.glide.load.resource.bitmap.ImageReader$InputStreamImageReader.getImageOrientation(ImageReader.java:204)
	at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeFromWrappedStreams(Downsampler.java:330)
	at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:285)
	at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:222)
	at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:62)
	at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:18)
	at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92)
	at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70)
	at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59)
	at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76)
	at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57)
	at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:539)
	at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:503)
	at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:489)
	at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:434)
	at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:399)
	at com.bumptech.glide.load.engine.SourceGenerator.onDataReadyInternal(SourceGenerator.java:211)
	at com.bumptech.glide.load.engine.SourceGenerator$1.onDataReady(SourceGenerator.java:101)
	at com.mplus.lib.ui.glide.InputStreamFactoryDataFetcher.loadData(InputStreamFactoryDataFetcher.java:33)
	at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:95)
	at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:88)
	at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:311)
	at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:280)
	at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:235)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
	at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:424)
	at java.lang.Thread.run(Thread.java:1012)
	at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultPriorityThreadFactory$1.run(GlideExecutor.java:383)

This is on Glide 4.16.0

TheoLassonder avatar Aug 12 '24 01:08 TheoLassonder