puppetlabs/puppet · error · ArgumentError
Could not find a valid module at %{path}
Error message
Could not find a valid module at %{path} What it means
`puppet module changes <path>` (the `changes` action of the module Face) raises ArgumentError when Puppet::ModuleTool.find_module_root(path) returns nil. find_module_root ascends from the given path looking for a directory containing metadata.json; if none exists at or above the path, no module can be located and the tool refuses to check it for modified files.
Source
Thrown at lib/puppet/face/module/changes.rb:29
EOT
returns _("Array of strings representing paths of modified files.")
examples <<-EOT
Show modified files of an installed module:
$ puppet module changes /etc/puppetlabs/code/modules/vcsrepo/
warning: 1 files modified
lib/puppet/provider/vcsrepo.rb
EOT
arguments _("<path>")
when_invoked do |path, options|
Puppet::ModuleTool.set_option_defaults options
root_path = Puppet::ModuleTool.find_module_root(path)
unless root_path
raise ArgumentError, _("Could not find a valid module at %{path}") % { path: path.inspect }
end
Puppet::ModuleTool::Applications::Checksummer.run(root_path, options)
end
when_rendering :console do |return_value|
if return_value.empty?
Puppet.notice _("No modified files")
else
Puppet.warning _("%{count} files modified") % { count: return_value.size }
end
return_value.map(&:to_s).join("\n")
end
end
end
View on GitHub (pinned to e227c27540)
Solutions
- cd into the module root (the directory containing metadata.json) and run `puppet module changes .`
- Verify a metadata.json exists: `ls <path>/metadata.json`; if missing, scaffold one with `puppet module generate` or copy from a module template
- Double-check the path for typos and confirm it points at a directory, not a single file
Example fix
# before puppet module changes ~/repos/controlrepo/site/roles # after cd ~/repos/controlrepo/site/roles/ntp && puppet module changes . # (only works once metadata.json exists in that module root)
Defensive patterns
Strategy: validation
Validate before calling
require 'pathname'
def module_root?(path)
Pathname.new(File.expand_path(path)).ascend.any? { |d| File.file?(File.join(d, 'metadata.json')) }
end
abort 'not a module: no metadata.json at or above this path' unless module_root?(ARGV[0] || Dir.pwd) Try / catch
begin
Puppet::Face[:module, :current].changes(path)
rescue ArgumentError => e
abort "#{e.message} — run from the directory containing metadata.json"
end Prevention
- Always run module-tool commands from the module root (where metadata.json lives)
- Include a metadata.json check in module scaffolding CI so unpackaged directories fail early
When it happens
Trigger: `puppet module changes /some/dir` where no metadata.json exists at or above that directory; passing a path to a single .pp file or a typo'd/nonexistent directory; running the command from the environment root instead of inside a module.
Common situations: Running from the wrong working directory; modules created before metadata.json was standard; control-repo role/profile directories that are not packaged modules; path typos.
Related errors
- Dependency conflict for %{module_name}: Dependency %{name} w
- Invalid 'name' field in metadata.json: %{err}
- Invalid 'version' field in metadata.json: %{err}
- field 'data_provider' contains non-alphanumeric characters
- field 'data_provider' must begin with a letter
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/77da274b29747740.
Report an issue: GitHub.