Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

FakeShellOut uses OpenStruct without requiring ostruct — NameError on the transport (target-mode) path

Open Beginner friendly
#287 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
1/5
Estimated time
Under an hour
Newbie friendliness
90/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
ruby
Domain
tooling

Research direction

Start in lib/mixlib/shellout/helper.rb at FakeShellOut#initialize around line 219, then run the Ruby reproduction from the issue with and without -rostruct. Confirm that constructing FakeShellOut no longer raises NameError and that status.success? still returns true without preloading ostruct.

Written by the indexing model from the issue text.

Description

Description

Mixlib::ShellOut::Helper::FakeShellOut#initialize calls OpenStruct.new (lib/mixlib/shellout/helper.rb:219 on main), but no file in the gem requires ostruct. On Ruby 3.x, OpenStruct isn't loaded unless something else in the process happens to require it, so constructing a FakeShellOut raises:

lib/mixlib/shellout/helper.rb:219:in `initialize': uninitialized constant Mixlib::ShellOut::Helper::FakeShellOut::OpenStruct (NameError)

FakeShellOut is used only on the transport path of __shell_out_command (when __transport_connection is set). That's Ohai / Chef target mode over a Train transport. Local shell_out never reaches it, which is presumably why it has gone unnoticed.

Impact

Running Ohai 19.1.40 in target mode (ohai --target <uri>) against a remote Linux host, every plugin that shells out throws this NameError. Ohai catches it and logs it only at trace level (Plugin Hostname threw #<NameError: ...>), so the run exits 0 and the attributes are simply missing: hostname, machinename, ipaddress, macaddress, network.interfaces, hostnamectl. The remote host returned correct output for every underlying command over the same transport.

With ostruct preloaded (RUBYOPT=-rostruct), the same target-mode run collects all of those attributes.

Reproduction

No transport or remote host needed:

require "mixlib/shellout/helper"
res = Struct.new(:stdout, :stderr, :exit_status).new("out", "", 0)
so  = Mixlib::ShellOut::Helper::FakeShellOut.new(["true"], {}, res)
puts so.status.success?
Command Result
ruby repro.rb NameError: uninitialized constant Mixlib::ShellOut::Helper::FakeShellOut::OpenStruct
ruby -rostruct repro.rb true

Observed with Ruby 3.1.6 and mixlib-shellout 3.3.6. The require list and the OpenStruct.new call are unchanged on main (latest tag v3.4.14): helper.rb requires only ../shellout, chef-utils, chef-utils/dsl/default_paths and chef-utils/internal, and no other file under lib/ references ostruct.

Suggested fix

Add require "ostruct" unless defined?(OpenStruct) to lib/mixlib/shellout/helper.rb. Alternatively, drop OpenStruct for a small Struct, since only success? is read.

Dominant language
Ruby
Stars
133
Forks
73
PR merge metrics
No merged PRs in 30d

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from chef/mixlib-shellout

All issues in chef/mixlib-shellout

Similar issues

More Ruby issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.