diff --git a/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb b/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb
index 093f08d1c160da05961dfcd469544f0ec020d338_ZmlsZXMvZ2l0bGFiLWN0bC1jb21tYW5kcy9saWIvZ2l0bGFiX2N0bC91dGlsLnJi..6ad5373e85839544e43c32a111e539b483f1867e_ZmlsZXMvZ2l0bGFiLWN0bC1jb21tYW5kcy9saWIvZ2l0bGFiX2N0bC91dGlsLnJi 100644
--- a/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb
+++ b/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb
@@ -100,7 +100,11 @@
 
       # Parse enabled roles out of the attributes json file and return an Array of Strings
       def roles(base_path)
-        get_node_attributes(base_path)['roles'].select { |k, v| v.key?('enable') && v['enable'] }.keys
+        roles = get_node_attributes(base_path)['roles']
+
+        return [] unless roles.is_a?(Hash)
+
+        roles.select { |k, v| v.key?('enable') && v['enable'] }.keys
       end
 
       def delay_for(seconds)
diff --git a/spec/gitlab-ctl-commands/lib/util_spec.rb b/spec/gitlab-ctl-commands/lib/util_spec.rb
index 093f08d1c160da05961dfcd469544f0ec020d338_c3BlYy9naXRsYWItY3RsLWNvbW1hbmRzL2xpYi91dGlsX3NwZWMucmI=..6ad5373e85839544e43c32a111e539b483f1867e_c3BlYy9naXRsYWItY3RsLWNvbW1hbmRzL2xpYi91dGlsX3NwZWMucmI= 100644
--- a/spec/gitlab-ctl-commands/lib/util_spec.rb
+++ b/spec/gitlab-ctl-commands/lib/util_spec.rb
@@ -83,6 +83,20 @@
       allow(File).to receive(:read).with(fake_node_file).and_return(roled_node.to_json)
       expect(described_class.roles(fake_base_path)).to eq(%w[role_one role_three])
     end
+
+    it 'when no roles are defined' do
+      roled_node = {}
+      allow(File).to receive(:read).with(fake_node_file).and_return(roled_node.to_json)
+
+      expect(described_class.roles(fake_base_path)).to eq([])
+    end
+
+    it 'when roles is not a Hash' do
+      roled_node = { roles: "test" }
+      allow(File).to receive(:read).with(fake_node_file).and_return(roled_node.to_json)
+
+      expect(described_class.roles(fake_base_path)).to eq([])
+    end
   end
 
   describe '#parse_json_file' do