{"record":{"id":"516624ccd3a4f3f1","repo":"puppetlabs/puppet","slug":"puppet-urls-are-not-supported-as-gem-sources","errorCode":null,"errorMessage":"puppet:// URLs are not supported as gem sources","messagePattern":"puppet:// URLs are not supported as gem sources","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/provider/package/gem.rb","lineNumber":240,"sourceCode":"    end\n\n    source = resource[:source]\n    if source\n      begin\n        uri = URI.parse(source)\n      rescue => detail\n        self.fail Puppet::Error, _(\"Invalid source '%{uri}': %{detail}\") % { uri: uri, detail: detail }, detail\n      end\n\n      case uri.scheme\n      when nil\n        # no URI scheme => interpret the source as a local file\n        command_options << source\n      when /file/i\n        command_options << uri.path\n      when 'puppet'\n        # we don't support puppet:// URLs (yet)\n        raise Puppet::Error, _(\"puppet:// URLs are not supported as gem sources\")\n      else\n        # check whether it's an absolute file path to help Windows out\n        if Puppet::Util.absolute_path?(source)\n          command_options << source\n        else\n          # interpret it as a gem repository\n          command_options << \"--source\" << source.to_s << resource[:name]\n        end\n      end\n    else\n      command_options << resource[:name]\n    end\n\n    output = self.class.execute_gem_command(command, command_options)\n    # Apparently some gem versions don't exit non-0 on failure.\n    self.fail _(\"Could not install: %{output}\") % { output: output.chomp } if output.include?(\"ERROR\")\n  end\n","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/provider/package/gem.rb#L222-L258","documentation":"gem.rb:240: while building gem install options, the provider parses the resource's source as a URI; a scheme of 'puppet' (puppet:// URLs from the file server) is explicitly rejected with Puppet::Error, because gem cannot fetch packages from Puppet's fileserver. Supported shapes are no scheme (local path), file:// paths, absolute paths, or a remote repository URL passed via --source.","triggerScenarios":"package { X: provider => gem, source => 'puppet:///modules/gems/x-1.0.gem' } — any attempt to install a .gem directly from the module mount. The URI parses fine (it was already validated as a URI), only the scheme check fails.","commonSituations":"Teams air-gapping gems try to serve them from the Puppet fileserver the same way they stage debs/rpms; converting a file { source => 'puppet://...' } pattern to package resources without adapting the URL.","solutions":["Stage the .gem with a file resource from puppet://, then pass the local path as the gem package's source.","Or serve gems from a real repository (file:// directory, https internal geminabox/artifactory) and point source at it.","Never use a puppet:// URL directly as a gem source — the provider rejects it by design."],"exampleFix":"# before\npackage { 'foo': ensure => installed, provider => 'gem', source => 'puppet:///modules/gems/foo-1.0.gem' }\n\n# after\nfile { '/tmp/foo-1.0.gem': source => 'puppet:///modules/gems/foo-1.0.gem', before => Package['foo'] }\npackage { 'foo': ensure => installed, provider => 'gem', source => '/tmp/foo-1.0.gem' }","handlingStrategy":"validation","validationCode":"# reject puppet:// schemes before declaring the resource\nuri = URI.parse(source.to_s)\nfail 'gem sources cannot be puppet:// — stage the file first' if uri.scheme == 'puppet'","typeGuard":"def valid_gem_source?(s)\n  u = URI.parse(s.to_s)\n  u.scheme.nil? || u.scheme =~ /file/i || %w[http https].include?(u.scheme)\nrescue URI::InvalidURIError\n  false\nend","tryCatchPattern":"begin\n  provider.install\nrescue Puppet::Error => e\n  raise unless e.message.include?('puppet:// URLs are not supported')\n  # stage from the fileserver, then install from the local copy\n  stage(source); resource[:source] = local_path; retry\nend","preventionTips":["Standardize on file-resource staging for gem artifacts served by Puppet.","Keep an internal gem server (geminabox/artifactory) for air-gapped installs instead of fileserver URLs.","Lint package sources: any puppet:// URL on a gem package is a config error by definition."],"tags":["puppet","rubygems","gem","url-scheme","packages"],"backgroundTag":"unsupported-url-scheme","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}