instructure/canvas-lms · error · ArgumentError
Zip File cannot have more than #
Error message
Zip File cannot have more than #{MAX_FILE_COUNT} entries What it means
validate_against in lib/unzip_attachment.rb:279 raises ArgumentError when the uploaded zip contains more than MAX_FILE_COUNT entries. Canvas rejects the archive up front before extraction to prevent resource exhaustion from very large zips.
Solutions
- Split the zip into smaller archives each under MAX_FILE_COUNT entries
- Upload the files in batches instead of one large zip
- Increase MAX_FILE_COUNT if the deployment legitimately needs larger zips (with capacity review)
- Inspect the zip's entry count locally (unzip -l) before uploading
Example fix
// before # course_export_with_10000_files.zip uploaded directly // after zip -r batch1.zip files_0001-0500/ zip -r batch2.zip files_0501-1000/ # each batch <= MAX_FILE_COUNT entries
Defensive patterns
Strategy: validation
Validate before calling
raise TooManyEntries if zip_entry_count(zip_path) > MAX_FILE_COUNT
Try / catch
begin
UnzipAttachment.process(context, zip)
rescue ArgumentError => e
render json: {error: e.message}, status: :bad_request
end Prevention
- Count zip entries (unzip -l) before upload
- Split large archives client-side
- Surface MAX_FILE_COUNT in UI guidance
When it happens
Trigger: Uploading a zip attachment to a course/folder whose entry count exceeds MAX_FILE_COUNT; calling UnzipAttachment with a zip containing thousands of small files.
Common situations: Instructors bulk-uploading course exports or LMS migration archives with many files; automated imports of content packages; students uploading zip assignments that explode into many entries.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- Zip contents exceed course quota limit
- Zip file would exceed quota limit
- A maximum of 50 assessees can be provided at once
- A maximum of 50 assessors can be provided at once
- A new_id, '# ', referenced an existing # and the # with #…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/1118d33e897ada06.
Report an issue: GitHub.
Appendix: source
Thrown at lib/unzip_attachment.rb:279
# quite seem appropriate to move it to it's own file
# since it's such an integral part of the unzipping
# process
class ZipFileStats
MAX_FILE_COUNT = 250_000
attr_reader :file_count, :total_size, :paths, :filename, :quota_remaining
def initialize(filename)
@filename = filename
@paths = []
@file_count = 0
@total_size = 0
@quota_remaining = nil
process!
end
def validate_against(context)
if file_count > MAX_FILE_COUNT
raise ArgumentError, "Zip File cannot have more than #{MAX_FILE_COUNT} entries"
end
# check whether the nominal size of the zip's contents would exceed
# quota, and reject the zip immediately if so
quota_hash = Attachment.get_quota(context)
if quota_hash[:quota] > 0
if (quota_hash[:quota_used] + total_size) > quota_hash[:quota]
raise Attachment::OverQuotaError, "Zip file would exceed quota limit"
end
@quota_remaining = quota_hash[:quota] - quota_hash[:quota_used]
end
end
# since the central directory can lie, track quota during extraction as well
# to prevent zip bomb denial-of-service attacks
def charge_quota(size)
return if @quota_remaining.nil?View on GitHub (pinned to 1c9f0bb801)