ruby/ruby · error · Bundler::InvalidOption

15

15

Error message

The request uri `#{uri}` has an invalid scheme (`#{uri.scheme}`). Did you mean `http` or `https`?

What it means

Downloader#validate_uri_scheme! runs before every request and rejects any URI whose scheme is not exactly `http` or `https` (case-sensitive, anchored match). It raises Bundler::InvalidOption, listing the offending URI and scheme, because RubyGems' fetcher only speaks HTTP(S).

Source

Thrown at lib/bundler/fetcher/downloader.rb:125

        Bundler.ui.trace e

        raise HTTPError, "Network error while fetching #{filtered_uri}" \
            " (#{e})"
      end

      private

      def network_down_error(uri, filtered_uri)
        host = uri.host
        host_port = "#{host}:#{uri.port}"
        host = host_port if filtered_uri.to_s.include?(host_port)
        NetworkDownError.new("Could not reach host #{host}. Check your network " \
          "connection and try again.")
      end

      def validate_uri_scheme!(uri)
        return if /\Ahttps?\z/.match?(uri.scheme)
        raise InvalidOption,
          "The request uri `#{uri}` has an invalid scheme (`#{uri.scheme}`). " \
          "Did you mean `http` or `https`?"
      end
    end
  end
end

View on GitHub (pinned to 0e5b888e1c)

Solutions

  1. Add or correct the scheme on every source/gem-source URL in the Gemfile to lowercase `http` or `https`.
  2. Prefer https; replace git:// URLs with https ones.
  3. If a non-HTTP source is intended (local path, git), use the proper DSL (`source "...", type:` plugin, `gem "x", path:`/`git:`) instead of a source URL.

Example fix

# Gemfile
# before
source "rubygems.org"
gem "rails", source: "git://internal.mirror"

# after
source "https://rubygems.org"
gem "rails", source: "https://internal.mirror"
Defensive patterns

Strategy: validation

Validate before calling

# lint every source URL before running bundler
require "uri"

sources = File.readlines("Gemfile").grep(/^\s*source\s+")").map { _1[/source\s+")([^"]+)"\)/, 1] }
bad = sources.reject { |s| /\Ahttps?\z/.match?(URI(s).scheme) }
abort "invalid source schemes: #{bad.join(', ')}" unless bad.empty?

Try / catch

begin
  definition.resolve_remotely!
rescue Bundler::InvalidOption => e
  abort "fix Gemfile source URL: #{e.message}" if e.message.include?("invalid scheme")
  raise
end

Prevention

When it happens

Trigger: A Gemfile source like `source "rubygems.org"` (no scheme, uri.scheme is nil), `source "git://github.com/..."`, `gem "x", source: "ftp://mirror/..."`, or a typo such as `https ://` or `HTTPS://` (the anchor match is lowercase-only).

Common situations: Hand-editing the Gemfile and dropping the scheme; copying a bare host from docs; legacy Gemfiles using git:// URLs that hosts have disabled; template variables producing empty schemes.

Related errors


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/768336ea430ee8e8. Report an issue: GitHub.