Chef Best Practices: undefined method `[]’ for nil:NilClass

Explains a common Chef failure pattern behind nil attribute errors and how to prevent hidden misconfiguration through proactive input validation. Provides practical patterns for verifying attribute presence and type early in recipe execution.

Coveros Staff

January 15, 2015

Typically you’ll get an error that looks like this:

NoMethodError

————-

undefined method `[]’ for nil:NilClass

 

Cookbook Trace:

—————

/cookbooks/test/recipes/default.rb:15:in `from_file’

 

Relevant File Content:

———————-

/cookbooks/test/recipes/default.rb:

 

12:

13:  puts “JPM Recipe start”

14:  puts node[‘att1’]

15>> puts node[‘att2’][‘att3’]

16:

What just happened? Well, this recipe just referenced a sub-attribute (‘att3’) of a primary attribute (‘att2’) that never existed.  So if no attributes exist at all, a call to:
   node[‘attr1’]
simply returns nil.  If you are unlucky enough to need this set, and didn’t check for it, then the recipe may still fail.  The most disturbing case is when it is automatically transmuted to an empty string by code like this:
  mypath = “#{node[‘base_path’]}/file.txt”
Now, this attribute which should have been set by a node-variable or an environment-variable goes unseen. And worse, because mypath becomes “/file.txt”, which is a perfectly valid path, the recipe may complete without error, but result in a completely invalid install.

In this case:
  node[‘att2’][‘att3’]
becomes
  nil[‘attr’]
which clearly fails because nil isn’t defined with the “[]” operator.

What should we do instead? You could always have better error checking.  Clearly, the standard approach is input validation.

Chef does provide a helper function “attribute?” located here.  But the standard ruby approach works for me. A attribute set like:

default[‘my_attrs’][‘firstname’]=”Jon”
default[‘my_attrs’][‘lastname’]=”Malachowski”

Could be generically verified:

raise “Attribute: my_attrs is not defined well” unless Hash === node[‘my_attrs’]
raise “Attribute: my_attrs->firstname is not defined well” unless String === node[‘my_attrs’][‘firstname’]
raise “Attribute: my_attrs->lastname is not defined well” unless String === node[‘my_attrs’][‘lastname’]

Coveros Staff

Coveros Staff

This post represents the collective insights of the Coveros team. Our staff consists of software experts who bring deep experience in secure agile development, DevOps, testing, and software quality. Over the past 20 years, Coveros has trained more than 30,000 professionals and worked with half of the Fortune 100 companies on mission-critical software development challenges. We draw on this extensive experience to share practical insights, proven strategies, and real-world solutions that help organizations build better software faster and more securely.