{"record":{"id":"83aad4479adaa8f6","repo":"puppetlabs/puppet","slug":"could-not-download-module-message","errorCode":null,"errorMessage":"Could not download module: %{message}","messagePattern":"Could not download module: %(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/puppet/module_tool/shared_behaviors.rb","lineNumber":173,"sourceCode":"      }\n    end\n    dependencies.each do |mod|\n      deps = @remote[\"#{mod[:module]}@#{mod[:version][:vstring]}\"].sort_by(&:first)\n      mod[:dependencies] = resolve_constraints(deps, source + [{ :name => mod[:module], :version => mod[:version][:vstring] }], seen, :install)\n    end unless @ignore_dependencies\n    dependencies\n  end\n\n  def download_tarballs(graph, default_path, forge)\n    graph.map do |release|\n      begin\n        if release[:tarball]\n          cache_path = Pathname(release[:tarball])\n        else\n          cache_path = forge.retrieve(release[:file])\n        end\n      rescue OpenURI::HTTPError => e\n        raise RuntimeError, _(\"Could not download module: %{message}\") % { message: e.message }, e.backtrace\n      end\n\n      [\n        { (release[:path] ||= default_path) => cache_path },\n        *download_tarballs(release[:dependencies], default_path, forge)\n      ]\n    end.flatten\n  end\n\n  def forced?\n    options[:force]\n  end\n\n  def add_module_name_constraints_to_graph(graph)\n    # Puppet modules are installed by \"module name\", but resolved by\n    # \"full name\" (including namespace).  So that we don't run into\n    # problems at install time, we should reject any solution that\n    # depends on multiple nodes with the same \"module name\".","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/module_tool/shared_behaviors.rb#L155-L191","documentation":"download_tarballs fetches each release tarball, either from a local path (release[:tarball]) or from the Forge via forge.retrieve. Any OpenURI::HTTPError during that fetch — 404, 403, 429, 5xx, or a proxy/TLS problem that surfaces as an HTTP error — is re-raised as a RuntimeError whose message embeds the HTTP error, with the original backtrace preserved. It is a transport failure, not a dependency-resolution failure.","triggerScenarios":"'puppet module install' when forge.retrieve gets an HTTP error: the tarball URL 404s (release deleted), the Forge rate-limits (429/403), a proxy intercepts forgeapi.puppet.com, or a custom forge baseurl points at a server that errors.","commonSituations":"Forge outages or rate limiting during mass CI installs; deprecated modules with releases removed; corporate proxies or SSL-inspection appliances breaking the download; private Forge mirrors missing the requested release.","solutions":["Retry after confirming Forge health (status.puppet.com) — transient 5xx/429 responses are the most common cause.","Verify the release exists: curl 'https://forgeapi.puppet.com/v3/releases?module=author-mod' or open the module page on forge.puppet.com.","Fix the network path: set https_proxy/no_proxy correctly for the puppet process, keep the CA bundle current, and exempt forgeapi.puppet.com from SSL inspection.","Pin versions known to exist and cache them locally (r10k/Puppetfile with a mirror) so installs survive Forge problems."],"exampleFix":"# before\n$ puppet module install puppetlabs-apt\nError: Could not download module: 503 Service Unavailable\n\n# after — correct proxy env and retry with backoff\n$ export no_proxy=forgeapi.puppet.com,forge.puppet.com\n$ for i in 1 2 3; do puppet module install puppetlabs-apt && break; sleep $((i*30)); done","handlingStrategy":"retry","validationCode":"require 'open-uri'\n# pre-flight: the tarball URL must respond before you install\nurl = 'https://forgeapi.puppet.com/v3/files/puppetlabs-apt-9.0.0.tar.gz'\nOpenURI.open_uri(url) { |f| puts 'ok: ' + f.status.first }","typeGuard":null,"tryCatchPattern":"tries = 0\nbegin\n  forge.retrieve(release[:file])\nrescue OpenURI::HTTPError => e\n  tries += 1\n  retry if tries < 3 && e.message =~ /503|429/\n  raise RuntimeError, \"module download failed after #{tries} tries: #{e.message}\"\nend","preventionTips":["Pre-flight the release URL in CI before mass installs.","Mirror the Forge internally (r10k cache or a Forge mirror) for reproducible installs.","Configure proxy and no_proxy for the puppet service user, not just your shell.","Pin module versions; floating 'latest' eventually hits removed releases."],"tags":["puppet","ruby","module-tool","forge","http","download","proxy"],"backgroundTag":"http-download-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}