Skip to content

More helpful exception when compressing large files in seek mode #43542

Closed

Description

@carlossanlop

When the user opens a stream in Create mode, and passes it to a ZipArchive opened in Update mode, then attempts to add a very large file to the zip, an exception will be thrown on dispose stating Stream was too long, which is confusing for the user, and frustrating if the file was large and this happens so late.

The exception is thrown because we restrict the size of a file to Int32.MaxValue. The restriction is reached because the Update mode requires a stream that allows seeking, so we internally create a MemoryStream so that we can update the archive, but the size limit for the file is Int32.MaxValue.

We do have it documented here, but it's not very obvious for the user to look for answers in that location.

We should explore two improvements:

  1. Throw a more helpful error message when this combination of conditions meet (Stream in Create mode, ZipArchive in Update mode, file too large).
  2. Try to detect this case much earlier, instead of waiting it to happen on Dispose.

I also opened to suggest a Roslyn analyzer that would help users avoid falling into this: #35815

This has been reported a few times already:

/cc @ericstj

Activity

  1. added this to the 6.0.0 milestone on Oct 16, 2020
  2. removed
    untriagedNew issue has not been triaged by the area owner
    on Oct 16, 2020
  3. modified the milestones: 6.0.0, 7.0.0 on Jul 26, 2021
  4. WinCPP commented on Jan 9, 2022

    @WinCPP
    Contributor

    @carlossanlop I am contributing after a long time and would like to attempt this.

  5. danmoseley commented on Jan 9, 2022

    @danmoseley
    Contributor

    @WinCPP welcome back! I will assign this to you. Let us know if you need help.

  6. WinCPP commented on Jan 14, 2022

    @WinCPP
    Contributor

    @WinCPP welcome back! I will assign this to you. Let us know if you need help.

    Thanks! And yes, I do need help 🙂

    As per the documentation, the file to be added to an archive in update mode cannot be larger than Int32.MaxValue in size. However, the following exception is thrown even when the size is Int32.MaxValue - 1.

          Message: 
    System.OutOfMemoryException : Array dimensions exceeded supported range.
    
          Stack Trace: 
    MemoryStream.set_Capacity(Int32 value) line 288
    MemoryStream.EnsureCapacity(Int32 value) line 165
    MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count) line 626
    WrappedStream.Write(Byte[] buffer, Int32 offset, Int32 count) line 155
    Stream.CopyTo(Stream destination, Int32 bufferSize) line 72
    BufferedFileStreamStrategy.CopyTo(Stream destination, Int32 bufferSize) line 945
    FileStream.CopyTo(Stream destination, Int32 bufferSize) line 508
    Stream.CopyTo(Stream destination) line 51
    ZipFileExtensions.DoCreateEntryFromFile(ZipArchive destination, String sourceFileName, String entryName, Nullable`1 compressionLevel) line 123
    ZipFileExtensions.CreateEntryFromFile(ZipArchive destination, String sourceFileName, String entryName, CompressionLevel compressionLevel) line 78
    ZipFile_ZipArchive_Create.CreateEntryFromLargeFileArchiveUpdateExtension(Boolean withCompressionLevel) line 52
    

    Here is the line that causes the exception (link).

    image

    Digging more, I found this discussion about mscorlib code over here. that mentions that the max possible index for a byte array is 0x7FFFFFC7 although the max size can be Int32.MaxValue. When I try with a file of size 0x7FFFFFC7 it works fine, but just a byte more i.e. 0x7FFFFFC8 and I get the above-mentioned exception. So should the logic for this fix use 0x7FFFFFC7 as the maximum allowable size instead of Int32.MaxValue? Appreciate your inputs.

    image

  7. modified the milestones: 7.0.0, 8.0.0 on Jul 9, 2022
  8. jeffhandley commented on Oct 22, 2022

    @jeffhandley
    Member

    Digging more, I found this discussion about mscorlib code over here. that mentions that the max possible index for a byte array is 0x7FFFFFC7 although the max size can be Int32.MaxValue. When I try with a file of size 0x7FFFFFC7 it works fine, but just a byte more i.e. 0x7FFFFFC8 and I get the above-mentioned exception. So should the logic for this fix use 0x7FFFFFC7 as the maximum allowable size instead of Int32.MaxValue? Appreciate your inputs.

    Hi @WinCPP. I'm sorry we missed your question here. I agree with your assessment here that we should cap the size to 0x7FFFFFC7 instead of Int32.MaxValue. Let us know if you would still like to contribute to this.

  9. WinCPP commented on Oct 22, 2022

    @WinCPP
    Contributor

    Hi, @jeffhandley thanks for the reply. I am busy with some office work ATM. So I am fine if someone wants to take this ahead.

  10. jeffhandley commented on Oct 25, 2022

    @jeffhandley
    Member

    Thanks, @WinCPP. And sorry again we missed your question earlier this year.

  11. modified the milestones: 8.0.0, Future on Jul 12, 2023
  12. alinpahontu2912 commented on Aug 25, 2025

    @alinpahontu2912
    Member

    Hey @jeffhandley @carlossanlop @WinCPP, this issue is still reproducible, and the maximum size I can use remains 0x7FFFFFC7. Would decreasing the maximum size for the MemoryStream class still be a viable solution?

    private const int MemStreamMaxLength = int.MaxValue;

  13. added
    in-prThere is an active PR which will close this issue when it is merged
    on Aug 26, 2025
  14. locked and limited conversation to collaborators on Oct 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area-System.IO.Compressionhelp wanted[up-for-grabs] Good issue for external contributorsin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions