instructure/canvas-lms · error · CanvasUnzip::UnknownArchiveType

invalid tar

Error message

invalid tar

What it means

CanvasUnzip.each_entry raises UnknownArchiveType "invalid tar" when the file was detected as a tar archive (via file magic or extension) but Gem::Package::TarReader raises TarInvalidError while reading entries — the tar structure is corrupt, truncated, or not really a tar despite the mime type.

Solutions

  1. Regenerate or re-upload the archive — the file itself is corrupt and cannot be salvaged.
  2. Validate the archive at upload time (tar -tf / Archive integrity check) and reject bad files early.
  3. Check file size vs stored size to detect truncated downloads from storage/S3.
  4. Verify mime detection isn't fooled: fall back on real content sniffing and reject files with mismatched extension/content.
  5. Wrap extraction with rescue CanvasUnzip::UnknownArchiveType to surface a friendly 'corrupt archive' message to users.

Example fix

// before
CanvasUnzip.extract_archive(path, dest) # raises UnknownArchiveType
// after
begin
  CanvasUnzip.extract_archive(path, dest)
rescue CanvasUnzip::UnknownArchiveType => e
  raise ImportFailure, "Corrupt or invalid archive: #{e.message}"
end
Defensive patterns

Strategy: validation

Validate before calling

unless system("tar", "-tf", path, out: File::NULL, err: File::NULL)
  raise CorruptArchive, "#{path} is not a valid tar"
end

Type guard

def intact_archive?(uploaded, stored_path)
  File.size(stored_path) == uploaded.size
end

Try / catch

begin
  CanvasUnzip.extract_archive(path, dest)
rescue CanvasUnzip::UnknownArchiveType => e
  raise CorruptArchiveError, "Archive is corrupt: #{e.message}"
end

Prevention

When it happens

Trigger: Uploading a truncated tar (partial download/aborted transfer); a gzip that decompresses to garbage but was detected as tar; concatenated or non-USTAR tar variants Gem can't parse; renamed files (e.g. a .txt renamed to .tar.gz) that mime detection still guesses as tar.

Common situations: Course import/export content packages that were cut off; users renaming arbitrary files to .tar to bypass upload checks; storage layer returning partial content; old/broken tars produced by nonstandard tools.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/4315321f6e8495b1. Report an issue: GitHub.

Appendix: source

Thrown at gems/canvas_unzip/lib/canvas_unzip.rb:148

    case mime_type
    when "application/zip"
      Zip::File.open(file) do |zipfile|
        zipfile.entries.each_with_index do |zip_entry, index|
          yield(Entry.new(zip_entry), index)
        end
      end
    when "application/x-tar"
      index = 0
      begin
        Gem::Package::TarReader.new(file).each do |tar_entry|
          next if tar_entry.header.typeflag == "x"

          yield(Entry.new(tar_entry), index)
          index += 1
        end
      rescue Gem::Package::TarInvalidError
        raise UnknownArchiveType, "invalid tar"
      end
    else
      raise UnknownArchiveType, "unknown mime type #{mime_type} for archive #{File.basename(archive_filename)}"
    end
  end

  def self.compute_uncompressed_size(archive_filename)
    total_size = 0
    each_entry(archive_filename) { |entry, _index| total_size += entry.size }
    total_size
  end

  class Entry
    attr_reader :entry, :type

    def initialize(entry)
      case entry
      when Zip::Entry

View on GitHub (pinned to 1c9f0bb801)