{"record":{"id":"5805dd7300af659a","repo":"puppetlabs/puppet","slug":"could-not-load-external-node-results-for-name","errorCode":null,"errorMessage":"Could not load external node results for %{name}: %{detail}","messagePattern":"Could not load external node results for %(.+?): %(.+?)","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/indirector/node/exec.rb","lineNumber":68,"sourceCode":"\n    node.fact_merge(facts)\n    node\n  end\n\n  # Translate the yaml string into Ruby objects.\n  def translate(name, output)\n    Puppet::Util::Yaml.safe_load(output, [Symbol]).each_with_object({}) do |data, hash|\n      case data[0]\n      when String\n        hash[data[0].intern] = data[1]\n      when Symbol\n        hash[data[0]] = data[1]\n      else\n        raise Puppet::Error, _(\"key is a %{klass}, not a string or symbol\") % { klass: data[0].class }\n      end\n    end\n  rescue => detail\n    raise Puppet::Error, _(\"Could not load external node results for %{name}: %{detail}\") % { name: name, detail: detail }, detail.backtrace\n  end\nend\n","sourceCodeStart":50,"sourceCodeEnd":71,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/indirector/node/exec.rb#L50-L71","documentation":"Catch-all wrapper around the exec node terminus's translate() step: any failure while parsing the ENC script's output with YAML.safe_load, or while normalizing its keys, is re-raised as Puppet::Error with the node name and the underlying detail. It covers malformed YAML (Psych::SyntaxError), disallowed classes (Aliases, unexpected tags) under safe_load, and non-hash-like structures (e.g., a scalar top level making each_with_object raise NoMethodError).","triggerScenarios":"ENC script prints warnings/deprecation notices before the YAML (making stdout invalid YAML), prints an empty string (safe_load returns nil/false and iteration fails), emits YAML aliases or symbols not whitelisted by safe_load, or crashes and the shell prints a stack trace to stdout which the terminus then tries to parse.","commonSituations":"ENC scripts that log to stdout instead of stderr; Ruby 3.x Psych defaults rejecting aliases; ENCs that silently die (exit non-zero) with stderr going to logs but stdout empty; scripts emitting multiple YAML documents.","solutions":["Run the ENC manually with a node name and validate the output: /path/to/enc.sh nodename.example.com | ruby -ryaml -e 'YAML.safe_load(STDIN, [Symbol]) or raise'","Send all diagnostics to stderr, never stdout, in the ENC script","Ensure the ENC always prints exactly one YAML hash (even an empty one: '--- {}') on success","If the output uses anchors/aliases, remove them or use YAML.safe_load(..., aliases: true) semantics on the ENC side by expanding aliases before dumping"],"exampleFix":"# before (ENC script)\nputs \"Looking up node...\"          # pollutes stdout -> Psych syntax error\nputs YAML.dump(result)\n\n# after\nwarn \"Looking up node...\"           # stderr only\nputs YAML.dump(result)              # stdout is pure YAML","handlingStrategy":"try-catch","validationCode":"output = `#{enc_script} #{Shellwords.escape(name)} 2>/dev/null`\nrequire 'yaml'\nbegin\n  YAML.safe_load(output, [Symbol])\nrescue Psych::Exception => e\n  raise Puppet::Error, \"ENC output is not valid YAML: #{e.message}\"\nend","typeGuard":null,"tryCatchPattern":"begin\n  node = Puppet::Node.indirection.find(certname)\nrescue Puppet::Error => e\n  raise unless e.message =~ /Could not load external node results/\n  # capture raw ENC output for diagnosis and re-raise with context\n  raw = `#{Puppet[:external_nodes]} #{Shellwords.escape(certname)}`\n  raise Puppet::Error, \"ENC raw output was: #{raw[0,200]}\"\nend","preventionTips":["ENC scripts must write diagnostics to stderr only","Always exit non-zero and print nothing on failure so failures are distinguishable from bad YAML","Smoke-test ENC output through YAML.safe_load in a CI job"],"tags":["puppet","external-nodes","enc","yaml","safe-load"],"backgroundTag":"yaml-parse-error","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}