{"record":{"id":"a71a19da179b5856","repo":"puppetlabs/puppet","slug":"could-not-extract-contents-of-module-archive-me","errorCode":null,"errorMessage":"Could not extract contents of module archive: %{message}","messagePattern":"Could not extract contents of module archive: %(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/puppet/forge.rb","lineNumber":228,"sourceCode":"      unless response.code == 200\n        raise Puppet::Forge::Errors::ResponseError.new(:uri => response.url, :response => response)\n      end\n    end\n\n    def validate_checksum(file, checksum, digest_class)\n      if Puppet.runtime[:facter].value(:fips_enabled) && digest_class == Digest::MD5\n        raise _(\"Module install using MD5 is prohibited in FIPS mode.\")\n      end\n\n      if digest_class.file(file.path).hexdigest != checksum\n        raise RuntimeError, _(\"Downloaded release for %{name} did not match expected checksum %{checksum}\") % { name: name, checksum: checksum }\n      end\n    end\n\n    def unpack(file, destination)\n      Puppet::ModuleTool::Applications::Unpacker.unpack(file.path, destination)\n    rescue Puppet::ExecutionFailure => e\n      raise RuntimeError, _(\"Could not extract contents of module archive: %{message}\") % { message: e.message }\n    end\n\n    def deprecated?\n      @data['module'] && !@data['module']['deprecated_at'].nil?\n    end\n  end\n\n  private\n\n  def process(list)\n    l = list.map do |release|\n      metadata = release['metadata']\n      begin\n        ModuleRelease.new(self, release)\n      rescue ArgumentError => e\n        Puppet.warning _(\"Cannot consider release %{name}-%{version}: %{error}\") % { name: metadata['name'], version: metadata['version'], error: e }\n        false\n      end","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/forge.rb#L210-L246","documentation":"Puppet raises this RuntimeError when a module tarball downloaded from the Forge cannot be extracted. The Unpacker shells out to the system tar; when tar exits non-zero, Puppet::ExecutionFailure is caught and re-raised with tar's message embedded. Root causes are almost always a corrupted or truncated archive (often the follow-on of a bad download), or a local tar that cannot handle the archive's compression format.","triggerScenarios":"A 'puppet module install' where the downloaded .tar.gz fails extraction: tar reports 'This does not look like a tar archive' or gzip reports 'unexpected end of file'. Also triggered when the module was packed with a compression the host tar lacks (for example xz or zstd on busybox or old GNU tar), or when extraction runs out of disk.","commonSituations":"Alpine or slim Docker images that ship busybox tar without xz/zstd support; truncated downloads behind flaky proxies; full filesystems during extraction; modules built by newer tooling being installed by agents with older tar binaries.","solutions":["Read the embedded tar message. It separates 'corrupt archive' from 'unsupported format'.","Download the tarball manually and run tar tzf <file>. If that fails, the archive itself is bad: re-download or fix the proxy/mirror, then retry the install.","If the format is the problem, install full extraction tooling on the node (apk add tar gzip xz, or apt-get install tar xz-utils) and retry.","Free disk space on the extraction target filesystem and retry.","Upgrade Puppet on the agent; newer versions support more compression formats and pass safer flags to tar."],"exampleFix":"# before: busybox tar cannot extract the forge tarball\nFROM alpine:3.19\nRUN apk add --no-cache ruby\n# puppet module install ... -> Could not extract contents of module archive: tar: unrecognized option\n\n# after: full GNU tar plus compression libraries before any module install\nFROM alpine:3.19\nRUN apk add --no-cache ruby tar gzip xz","handlingStrategy":"retry","validationCode":"# Verify the extractors the Unpacker shells out to before installing modules\n%w[tar gzip].each do |bin|\n  abort \"missing extractor: #{bin}\" unless Puppet::Util::Which.which(bin)\nend","typeGuard":null,"tryCatchPattern":"begin\n  Puppet::ModuleTool::Applications::Installer.run(mod, modulepath: mp)\nrescue RuntimeError => e\n  raise unless e.message =~ /Could not extract contents of module archive/\n  raise unless e.message.include?('tar')  # tooling problem: do not blind-retry\n  system('apk add tar xz') || system('apt-get install -y tar xz-utils')\n  retry_once ? (retry_once = false; retry) : raise\nend","preventionTips":["Base agent images on full distros with GNU tar, gzip, and xz installed.","Catch checksum failures upstream so corrupt tarballs never reach extraction.","Monitor disk space on the module cache and extraction filesystems.","Test module installs in the same container image you deploy."],"tags":["puppet","forge","module-install","tar","extraction"],"backgroundTag":"archive-extraction-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}