{"record":{"id":"981e37d7eb95ba2f","repo":"instructure/canvas-lms","slug":"zip-file-would-exceed-quota-limit","errorCode":null,"errorMessage":"Zip file would exceed quota limit","messagePattern":"Zip file would exceed quota limit","errorType":"validation","errorClass":"Attachment::OverQuotaError","httpStatus":null,"severity":"error","filePath":"lib/unzip_attachment.rb","lineNumber":287,"sourceCode":"    @filename = filename\n    @paths = []\n    @file_count = 0\n    @total_size = 0\n    @quota_remaining = nil\n    process!\n  end\n\n  def validate_against(context)\n    if file_count > MAX_FILE_COUNT\n      raise ArgumentError, \"Zip File cannot have more than #{MAX_FILE_COUNT} entries\"\n    end\n\n    # check whether the nominal size of the zip's contents would exceed\n    # quota, and reject the zip immediately if so\n    quota_hash = Attachment.get_quota(context)\n    if quota_hash[:quota] > 0\n      if (quota_hash[:quota_used] + total_size) > quota_hash[:quota]\n        raise Attachment::OverQuotaError, \"Zip file would exceed quota limit\"\n      end\n\n      @quota_remaining = quota_hash[:quota] - quota_hash[:quota_used]\n    end\n  end\n\n  # since the central directory can lie, track quota during extraction as well\n  # to prevent zip bomb denial-of-service attacks\n  def charge_quota(size)\n    return if @quota_remaining.nil?\n    if size > @quota_remaining\n      raise Attachment::OverQuotaError, \"Zip contents exceed course quota limit\"\n    end\n\n    @quota_remaining -= size\n  end\n\n  def paths_with_positions(base)","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/unzip_attachment.rb#L269-L305","documentation":"validate_against in lib/unzip_attachment.rb:287 raises Attachment::OverQuotaError when the zip's nominal total uncompressed size plus the context's current quota usage would exceed the context quota. Canvas checks this pre-extraction using Attachment.get_quota so oversized zips are rejected immediately.","triggerScenarios":"extracting/unzipping into a course or user context where quota_hash[:quota_used] + total_size > quota_hash[:quota] and quota is non-zero; typical call sites are Attachment.zip uploads or course copy/import unzipping into a files area.","commonSituations":"Instructor near their course file quota uploads a large media zip; importing a course export archive bigger than remaining space; account with small quota configured receiving bulk content uploads.","solutions":["Free up file quota in the target course/user (delete unneeded files) before uploading","Upload a smaller zip or upload files individually as space allows","Ask an admin to raise the quota for the course/user/account","Check remaining space via the files page quota indicator before attempting the upload"],"exampleFix":"// before\nUnzipAttachment.process(course, 'big_media_20gb.zip') # quota_used + 20GB > quota\n// after\n# delete unused files to free space, or request quota increase, then retry upload","handlingStrategy":"try-catch","validationCode":"quota = Attachment.get_quota(context)\nraise OverQuotaError if quota[:quota] > 0 && quota[:quota_used] + zip_total_size > quota[:quota]","typeGuard":null,"tryCatchPattern":"begin\n  UnzipAttachment.process(context, zip)\nrescue Attachment::OverQuotaError => e\n  flash[:error] = e.message\nend","preventionTips":["Check the files-page quota indicator before bulk uploads","Clean up unused course files regularly","Prefer uploading subsets when near quota"],"tags":["ruby","zip","quota","upload"],"backgroundTag":"quota-exceeded","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}