Bad URI(is Not URI?): (URI::InvalidURIError)

gems, ruby, rubygems

In this post, I examine a bad URI(is not URI?) error that I received while running gem install and dive into the rubygems source code to diagnose the issue.

1
bad URI(is not URI?):  (URI::InvalidURIError)

I stumbled across the above error a number of times at work when running gem install. It was nothing short of frustrating since every time I did a search for the string I came up with nothing related to rubygems or the gem command. Here’s the full stacktrace:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.../uri/common.rb:176:in `split': bad URI(is not URI?):  (URI::InvalidURIError)
.../uri/common.rb:212:in `parse'
.../uri/common.rb:748:in `parse'
.../rubygems/source_list.rb:58:in `<<'
.../rubygems/source_list.rb:73:in `block in replace'
.../rubygems/source_list.rb:72:in `each'
.../rubygems/source_list.rb:72:in `replace'
.../rubygems/source_list.rb:38:in `from'
.../rubygems.rb:867:in `sources='
.../rubygems/config_file.rb:225:in `initialize'
.../rubygems/gem_runner.rb:74:in `new'
.../rubygems/gem_runner.rb:74:in `do_configuration'
.../rubygems/gem_runner.rb:39:in `run'
.../bin/gem:22:in `<main>'

Since Google wasn’t going to solve the problem for me, I had to jump into the source code myself to address the issue. It took running through the rubygems code to actually discover that problem was how sources was defined.

How does rubygems define sources?

In ruby gems there are multiple ways to define sources. The first is the most basic, the default gem source is https://rubygems.org.

The second way to set your gem sources is via a gemrc file. The gemrc file can be defined in 3 different locations:

  • system wide /etc/gemrc
  • per user ~/.gemrc
  • per environment (gemrc files listed in GEMRC environment variable)

The final place where gem sources can be defined is in bundler:

1
2
3
4
5
6
7
source "http://rubygems.org"
source "http://my-private-gemstore.com"

gem 'sinatra'
gem 'rake'

# etc ...

By going through the various locations for defining sources above, I was able to find a gemrc file that was missing an entry for sources:

1
2
3
---
:sources:
-          # should be https://rubygems.org

By filling in the blank item under sources to https://rubygems.org, my problem was resolved.

Why not use RubyGems as the only source?

If you’re newer to ruby, or have never used a private gem repo you’re probably asking why allow multiple source definitions?

Let’s look at the historical side. Back in the day there used to multiple sources of gems. As the ruby community aged these sites either migrated to rubygems.org or shutdown altogether. In cronological order:

Prior to consolidation, you’d need to define all the sources that you were pulling your gems from. This is one reason why you’re able to define multiple sources today.

The second reason that you can define multiple sources for ruby gems is private gem repos. Private repos are a way to privately host gems without giving access to the outside world. There are various use cases for this: ip restrictions, security considerations, etc. which is why you or your company might do this.

If you’re interested, there are a couple of ways to host your gems privately via:

This page was delicately crafted on by Gavin Miller.