{"record":{"id":"20b410fba08c7ef0","repo":"puppetlabs/puppet","slug":"failed-to-find-name-via-exec-detail","errorCode":null,"errorMessage":"Failed to find %{name} via exec: %{detail}","messagePattern":"Failed to find %(.+?) via exec: %(.+?)","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/indirector/exec.rb","lineNumber":23,"sourceCode":"\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\n\n  # Proxy the execution, so it's easier to test.\n  def execute(command, arguments)\n    Puppet::Util::Execution.execute(command, arguments)\n  end\nend\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/indirector/exec.rb#L5-L41","documentation":"When the exec terminus actually runs the external command (with failonfail and separated stderr) and the process exits non-zero, Puppet::ExecutionFailure is caught and re-raised as Puppet::Error with the command's failure detail and the original backtrace attached. The looked-up name is appended as the command's last argument before execution, and the message embeds both the name and the stderr/failure detail.","triggerScenarios":"ENC script exits non-zero (missing gem, syntax error, upstream API failure); script not executable or with a broken shebang; permission denied on the script file.","commonSituations":"ENC scripts with unhandled exceptions on unusual node names; scripts depending on gems present in an interactive shell but not in the puppetserver/puppet Ruby environment; deploy pipelines shipping a script without the executable bit or with CRLF-mangled shebangs.","solutions":["Run the exact command by hand with a node name: /etc/puppet/node.rb node1.example.com — the output you see is the embedded detail","Fix the script's crash (missing require, nil data, upstream API down) and make it exit 0 with empty output for 'not found'","Check mode and shebang: chmod +x, LF line endings, interpreter exists in the service's environment"],"exampleFix":"# before: /etc/puppet/node.rb raises (missing gem)\n# => Puppet::Error: Failed to find node1 via exec: ... LoadError ...\n\n# after: vendor/install the dependency, then verify\n#   /etc/puppet/node.rb node1.example.com; echo $?   # => 0","handlingStrategy":"try-catch","validationCode":"# ruby\nok = system(Puppet[:external_nodes], name, out: File::NULL, err: File::NULL)\nPuppet.warning \"ENC failing for #{name}\" unless ok\n# run the terminus only when the pre-flight succeeds","typeGuard":"def enc_runnable?(name)\n  system(Puppet[:external_nodes], name, out: File::NULL, err: File::NULL)\nend","tryCatchPattern":"begin\n  result = terminus.find(request)\nrescue Puppet::Error => e\n  raise unless e.message.include?('via exec')\n  Puppet.err(e.message)  # message embeds the script's failure detail\n  nil  # treat as node-not-found, or alert\nend","preventionTips":["Test ENC scripts from the same Ruby environment puppetserver uses, not your shell","Make ENCs exit 0 with empty output for 'not found' instead of crashing on unknown nodes","Ship ENCs with the executable bit, LF line endings, and a shebang that exists on the server"],"tags":["puppet-indirector","exec-terminus","enc","process-execution"],"backgroundTag":"external-command-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}