Searching for nil in all the wrong places...
A few days ago, I was adding some migrations to a Ruby on Rails project, but when I went to initialize a newly created database, I saw this error:
- rake aborted!
- You have a nil object when you didn't expect it!
- You might have expected an instance of Array.
- The error occured while evaluating nil.first
This being the third or so time working in Ruby, I immediately thought that it was something I did, so I started up the automatically generated scripts/application
, pasted my new code into there, and proceeded to use it. The code had a couple issues that I fixed and I was confident enough to try again.
But again, I got the same error message. I then decided to add a couple prints around the new code, and re-run it, but the error above occurred without my print outs. Not sure how to proceed, I asked for some assistance from some co-workers. The advice was great, and I learned a lot about Ruby and Rails, but it still did not resolve my problem.
Finally someone recommended adding --trace
to the my command:
- eyt@zaterdag 5031% rake --trace migrate
- ** Invoke migrate (first_time)
- ** Invoke environment (first_time)
- ** Execute environment
- ** Execute migrate
- rake aborted!
- You have a nil object when you didn't expect it!
- You might have expected an instance of Array.
- The error occured while evaluating nil.first
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:253:in `migration_files'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `sort_by'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `each'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `sort_by'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:252:in `migration_files'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:235:in `migration_classes'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:223:in `migrate'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:190:in `up'
- .../lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/migration.rb:181:in `migrate'
- .../lib/ruby/gems/1.8/gems/rails-1.0.0/lib/tasks/databases.rake:3
- .../lib/ruby/gems/1.8/gems/rails-1.0.0/lib/tasks/databases.rake:2:in `call'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:in `execute'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:in `each'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:202:in `execute'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:180:in `invoke'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:in `run'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:in `each'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake.rb:1454:in `run'
- .../lib/ruby/gems/1.8/gems/rake-0.6.2/bin/rake:7
- .../bin/rake:18:in `load'
- .../bin/rake:18
So that is very interesting. Note how there is nothing in the above points to anything of mine. In pondering this with one of my coworkers, I explained how one of the things that I tried during debugging it was renaming the name of the class and filename, and that struck a cord.
It turns out that the mess above was all caused by my filename. I had named my file revision_add_blah_to_myApp
and named my class AddBlahToMyApp
. The problem with this is that the Rails convention for class names requires me to either name my file revision_add_blah_to_my_app
or name my class AddBlahToMyapp
. This very subtle issue caused this most unusable error message to cause a few completely wasted hours.
I have blogged before about great and not so great exceptions and their handling. I think this also falls in that category of not-so-great. It would have been nice to know that this problem originated with an attempt to load a class that did not exist, for example. In that case, I would have looked at that issue more closer than looking for references to first
(and indirect references thereof) where the object invoking that method could have been nil.