{"record":{"id":"05ceb0600b8fddce","repo":"puppetlabs/puppet","slug":"value-of-opts-must-be-a-hash","errorCode":null,"errorMessage":"value of %{opts} must be a hash","messagePattern":"value of %(.+?) must be a hash","errorType":"exception","errorClass":"Puppet::DataBinding::LookupError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/lookup/lookup_adapter.rb","lineNumber":300,"sourceCode":"\n  def global_only?\n    instance_variable_defined?(:@global_only) ? @global_only : false\n  end\n\n  # Instructs the lookup framework to only perform lookups in the global layer\n  # @return [LookupAdapter] self\n  def set_global_only\n    @global_only = true\n    self\n  end\n\n  private\n\n  PROVIDER_STACK = [:lookup_global, :lookup_in_environment, :lookup_in_module].freeze\n\n  def validate_lookup_options(options, module_name)\n    return nil if options.nil?\n    raise Puppet::DataBinding::LookupError, _(\"value of %{opts} must be a hash\") % { opts: LOOKUP_OPTIONS } unless options.is_a?(Hash)\n    return options if module_name.nil?\n\n    pfx = \"#{module_name}::\"\n    options.each_pair do |key, _value|\n      if key.start_with?(LOOKUP_OPTIONS_PATTERN_START)\n        unless key[1..pfx.length] == pfx\n          raise Puppet::DataBinding::LookupError, _(\"all %{opts} patterns must match a key starting with module name '%{module_name}'\") % { opts: LOOKUP_OPTIONS, module_name: module_name }\n        end\n      else\n        unless key.start_with?(pfx)\n          raise Puppet::DataBinding::LookupError, _(\"all %{opts} keys must start with module name '%{module_name}'\") % { opts: LOOKUP_OPTIONS, module_name: module_name }\n        end\n      end\n    end\n  end\n\n  def compile_patterns(options)\n    return nil if options.nil?","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/lookup/lookup_adapter.rb#L282-L318","documentation":"LookupAdapter#validate_lookup_options is the entry gate for the special 'lookup_options' key found in data: before any pattern or key handling, it requires the value to be a Hash, otherwise Puppet::DataBinding::LookupError 'value of lookup_options must be a hash' is raised. lookup_options must always be a mapping of data keys (or '^' regex patterns) to option hashes like {'convert_to' => ..., 'merge' => ...}.","triggerScenarios":"A data file containing `lookup_options: true`, `lookup_options: [a, b]`, or `lookup_options: 'auto'` (string); YAML indentation error making the value a scalar; using lookup_options as a flag instead of a map.","commonSituations":"Teams toggling lookup_options on/off as a boolean; malformed YAML where nested options de-indented into a scalar; copy-paste from notes that drop the mapping structure.","solutions":["Make lookup_options a mapping: `lookup_options: { 'mykey': { 'merge' => 'deep' } }`.","If you do not want options, delete the lookup_options entry entirely rather than setting a non-hash value.","Run the data file through a YAML linter — indentation mistakes are the usual root cause."],"exampleFix":"# before: data/common.yaml\nlookup_options: 'enabled'\n\n# after\nlookup_options:\n  myapp::config:\n    merge: deep","handlingStrategy":"validation","validationCode":"# CI check: any lookup_options key in data must map to a Hash\nrequire 'yaml'\n\nDir['**/data/**/*.yaml'].each do |f|\n  lo = YAML.load_file(f)['lookup_options']\n  next if lo.nil?\n  abort \"#{f}: lookup_options must be a Hash, got #{lo.class}\" unless lo.is_a?(Hash)\nend","typeGuard":null,"tryCatchPattern":null,"preventionTips":["lookup_options is always a map of key/pattern → options hash; never a scalar or list.","Lint YAML data files (yamllint) so indentation produces the structure you intended.","To disable options for a key, delete its entry — do not change lookup_options' shape."],"tags":["puppet","hiera","lookup-options","type-validation","yaml"],"backgroundTag":"hiera-lookup-options-not-hash","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}