puppetlabs/puppet · error · Puppet::DataBinding::LookupError
all %{opts} keys must start with module name '%{module_name}
Error message
all %{opts} keys must start with module name '%{module_name}' What it means
The plain-key counterpart of the pattern rule: inside module-sourced lookup_options, every key that does not start with '^' must literally start with '<module_name>::' (key.start_with?(pfx)), otherwise Puppet::DataBinding::LookupError is raised. A module's data can only configure lookup options for its own namespaced keys, preventing one module from shadowing options of others.
Source
Thrown at lib/puppet/pops/lookup/lookup_adapter.rb:311
private
PROVIDER_STACK = [:lookup_global, :lookup_in_environment, :lookup_in_module].freeze
def validate_lookup_options(options, module_name)
return nil if options.nil?
raise Puppet::DataBinding::LookupError, _("value of %{opts} must be a hash") % { opts: LOOKUP_OPTIONS } unless options.is_a?(Hash)
return options if module_name.nil?
pfx = "#{module_name}::"
options.each_pair do |key, _value|
if key.start_with?(LOOKUP_OPTIONS_PATTERN_START)
unless key[1..pfx.length] == pfx
raise Puppet::DataBinding::LookupError, _("all %{opts} patterns must match a key starting with module name '%{module_name}'") % { opts: LOOKUP_OPTIONS, module_name: module_name }
end
else
unless key.start_with?(pfx)
raise Puppet::DataBinding::LookupError, _("all %{opts} keys must start with module name '%{module_name}'") % { opts: LOOKUP_OPTIONS, module_name: module_name }
end
end
end
end
def compile_patterns(options)
return nil if options.nil?
key_options = {}
pattern_options = {}
options.each_pair do |key, value|
if key.start_with?(LOOKUP_OPTIONS_PATTERN_START)
pattern_options[Regexp.compile(key)] = value
else
key_options[key] = value
end
end
[key_options.empty? ? nil : key_options, pattern_options.empty? ? nil : pattern_options]View on GitHub (pinned to e227c27540)
Solutions
- Prefix every plain lookup_options key in module data with your module name: 'mymodule::key'.
- Move options for keys outside your module to environment-level data.
- If the key is a regex intent, use '^mymodule::...' pattern syntax instead (subject to the pattern rule).
Example fix
# before: modules/mymodule/data/common.yaml
lookup_options:
mykey:
convert_to: 'Integer'
# after
lookup_options:
mymodule::mykey:
convert_to: 'Integer' Defensive patterns
Strategy: validation
Validate before calling
# CI check: plain lookup_options keys in module data must be module-namespaced
require 'yaml'
Dir['modules/*/data/**/*.yaml'].each do |f|
mod = f.split('/')[1]
(YAML.load_file(f)['lookup_options'] || {}).each_key do |key|
next if key.start_with?('^')
abort "#{f}: key '#{key}' must start with '#{mod}::'" unless key.start_with?("#{mod}::")
end
end Prevention
- Spell out the full namespace ('mymodule::key') in every module-data lookup_options entry.
- Options for keys owned by other modules belong in the environment's data, not the module's.
- Add the namespace check to the same CI lint pass as the pattern check.
When it happens
Trigger: modules/mymodule/data/common.yaml with `lookup_options: { 'myothermodule::key': {...} }` or an unnamespaced `lookup_options: { 'mykey': {...} }` — neither starts with 'mymodule::'.
Common situations: Module data written before namespacing rules were understood; environment data copied into a module; keys missing the module prefix because the author assumed module context is implicit.
Related errors
- all %{opts} patterns must match a key starting with module n
- Invalid data type in lookup_options for key '%{key}' could n
- The convert_to lookup_option for key '%{key}' raised error:
- value of %{opts} must be a hash
- Undefined variable '%{name}'; %{reason}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/75fdb6bdaadb59e8.
Report an issue: GitHub.