puppetlabs/puppet · error · FaultyMetadata
%{name} has an invalid and unparsable metadata.json file. Th
Error message
%{name} has an invalid and unparsable metadata.json file. The parse error: %{error} What it means
Puppet::Module's metadata reader parses a module's metadata.json with Puppet::Util::Json and, on ParseError, reports 'invalid and unparsable metadata.json' with the underlying parser message (lib/puppet/module.rb:238). What happens next depends on the `strict` setting: :off logs to debug, :warning emits a warning, :error raises Puppet::Module::FaultyMetadata. The same broken file is therefore either noise or a hard failure purely by configuration.
Source
Thrown at lib/puppet/module.rb:238
def read_metadata
md_file = metadata_file
return {} if md_file.nil?
content = File.read(md_file, :encoding => 'utf-8')
content.empty? ? {} : Puppet::Util::Json.load(content)
rescue Errno::ENOENT
{}
rescue Puppet::Util::Json::ParseError => e
# TRANSLATORS 'metadata.json' is a specific file name and should not be translated.
msg = _("%{name} has an invalid and unparsable metadata.json file. The parse error: %{error}") % { name: name, error: e.message }
case Puppet[:strict]
when :off
Puppet.debug(msg)
when :warning
Puppet.warning(msg)
when :error
raise FaultyMetadata, msg
end
{}
end
def load_metadata
return if instance_variable_defined?(:@metadata)
@metadata = data = read_metadata
return if data.empty?
@forge_name = data['name'].tr('-', '/') if data['name']
[:source, :author, :version, :license, :dependencies].each do |attr|
value = data[attr.to_s]
raise MissingMetadata, "No #{attr} module metadata provided for #{name}" if value.nil?
if attr == :dependencies
unless value.is_a?(Array)View on GitHub (pinned to e227c27540)
Solutions
- Validate and repair the JSON: `ruby -rjson -e 'JSON.parse(File.read("metadata.json"))'` or any JSON linter — the parser message in the error pinpoints the offset
- Regenerate metadata.json with pdk or `puppet module generate`, which emits valid JSON
- If third-party modules must be tolerated despite bad metadata, set `strict = warning` instead of :error — but fixing the file is the real remedy
Example fix
// before (metadata.json)
{
"name": "acme-web",
"version": "1.0.0",
"license": "Apache-2.0",
"dependencies": [],
}
// after
{
"name": "acme-web",
"version": "1.0.0",
"license": "Apache-2.0",
"dependencies": []
} Defensive patterns
Strategy: try-catch
Validate before calling
def valid_module_metadata?(dir) path = File.join(dir, 'metadata.json') return true unless File.exist?(path) Puppet::Util::Json.load(File.read(path)) true rescue Puppet::Util::Json::ParseError, Errno::ENOENT false end
Try / catch
begin
mod = Puppet::Module.find(name, environment)
mod.load_metadata if mod
rescue Puppet::Module::FaultyMetadata => e
Puppet.warning("skipping module #{name}: #{e.message}")
next
end Prevention
- Lint metadata.json (pdk validate, metadata-json-lint) in CI before modules ship
- Never hand-edit JSON casually — regenerate via pdk when possible
- Know your `strict` mode: only strict=error turns bad metadata into FaultyMetadata exceptions
When it happens
Trigger: metadata.json with a trailing comma, comment, single-quoted strings, or BOM; a truncated file from an interrupted module install; running with `strict = error` in puppet.conf while any installed module has malformed metadata.
Common situations: Hand-edited metadata.json; modules generated by non-Puppet tooling; CI enforcing strict=error; files saved as UTF-16.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- No #{attr} module metadata provided for #{name}
- The value for the key dependencies in the file metadata.json
- Could not find a valid module at %{path}
- Cannot manage files of type %{file_type}
- Invalid module name '%{name}'; module names must match eithe
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/7f6f748579250f07.
Report an issue: GitHub.