{"record":{"id":"9680fd3b0b401b00","repo":"puppetlabs/puppet","slug":"you-must-set-the-exec-parameter-to-a-fully-qualifi","errorCode":null,"errorMessage":"You must set the exec parameter to a fully qualified command","messagePattern":"You must set the exec parameter to a fully qualified command","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/indirector/exec.rb","lineNumber":16,"sourceCode":"# frozen_string_literal: true\n\nrequire_relative '../../puppet/indirector/terminus'\nrequire_relative '../../puppet/util'\n\nclass Puppet::Indirector::Exec < Puppet::Indirector::Terminus\n  # Look for external node definitions.\n  def find(request)\n    name = request.key\n    external_command = command\n\n    # Make sure it's an array\n    raise Puppet::DevError, _(\"Exec commands must be an array\") unless external_command.is_a?(Array)\n\n    # Make sure it's fully qualified.\n    raise ArgumentError, _(\"You must set the exec parameter to a fully qualified command\") unless Puppet::Util.absolute_path?(external_command[0])\n\n    # Add our name to it.\n    external_command << name\n    begin\n      output = execute(external_command, :failonfail => true, :combine => false)\n    rescue Puppet::ExecutionFailure => detail\n      raise Puppet::Error, _(\"Failed to find %{name} via exec: %{detail}\") % { name: name, detail: detail }, detail.backtrace\n    end\n\n    if output =~ /\\A\\s*\\Z/ # all whitespace\n      Puppet.debug { \"Empty response for #{name} from #{self.name} terminus\" }\n      nil\n    else\n      output\n    end\n  end\n\n  private","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/indirector/exec.rb#L1-L34","documentation":"The exec terminus (used for external node classifiers and other exec-backed indirections) requires its configured command to be an Array whose first element is a fully qualified (absolute) path. If external_command[0] is not absolute — e.g. 'node.rb' or 'scripts/node.rb' — ArgumentError is raised before anything is executed.","triggerScenarios":"Setting the terminus's exec setting (e.g. external_nodes = node.rb or ./get_node.sh) with a relative path; templated paths that interpolate to an empty or relative value.","commonSituations":"puppet.conf external_nodes entry written without a leading slash that works in one cwd and breaks when the master's cwd changes; bootstrap scripts templating the path relative to a modules dir; porting configs to or from Windows where the absolute prefix differs.","solutions":["Use an absolute path in the setting: external_nodes = /etc/puppetlabs/puppet/node.rb","When templating, expand at write time: File.expand_path(path) when generating the config","Confirm the file exists and is executable after fixing the path"],"exampleFix":"# before (puppet.conf)\nexternal_nodes = node.rb\nnode_terminus  = exec\n# => ArgumentError: You must set the exec parameter to a fully qualified command\n\n# after\nexternal_nodes = /etc/puppetlabs/puppet/node.rb\nnode_terminus  = exec","handlingStrategy":"validation","validationCode":"# ruby\ncmd = Puppet[:external_nodes]\nraise ArgumentError, 'external_nodes must be absolute' unless Puppet::Util.absolute_path?(cmd)\nraise ArgumentError, 'external_nodes missing/not executable' unless File.executable?(cmd)","typeGuard":"def absolute_executable?(cmd)\n  Puppet::Util.absolute_path?(cmd) && File.executable?(cmd)\nend","tryCatchPattern":"begin\n  terminus.find(request)\nrescue ArgumentError => e\n  raise unless e.message.include?('fully qualified')\n  Puppet[:external_nodes] = File.expand_path(Puppet[:external_nodes])\n  retry\nend","preventionTips":["Always write absolute paths in external_nodes and exec settings","Run File.expand_path when templating puppet.conf from relative inputs","Smoke-test the ENC path after provisioning: test -x /etc/puppet/node.rb"],"tags":["puppet-indirector","exec-terminus","enc","path-validation"],"backgroundTag":"invalid-command-path","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}