puppetlabs/puppet · error · ArgumentError
Could not parse JSON %{metadata_path}
Error message
Could not parse JSON %{metadata_path} What it means
Application#metadata raises ArgumentError('Could not parse JSON <path>') when Puppet::Util::Json.load fails with Puppet::Util::Json::ParseError while reading the module's metadata.json. The file exists but is not valid JSON (or not UTF-8 clean), so its contents cannot be trusted for build/install decisions. The original backtrace is attached as the third raise argument.
Source
Thrown at lib/puppet/module_tool/applications/application.rb:59
return @metadata if @metadata
@metadata = Puppet::ModuleTool::Metadata.new
unless @path
raise ArgumentError, _("Could not determine module path")
end
if require_metadata && !Puppet::ModuleTool.is_module_root?(@path)
raise ArgumentError, _("Unable to find metadata.json in module root at %{path} See https://puppet.com/docs/puppet/latest/modules_publishing.html for required file format.") % { path: @path }
end
metadata_path = File.join(@path, 'metadata.json')
if File.file?(metadata_path)
File.open(metadata_path) do |f|
@metadata.update(Puppet::Util::Json.load(f))
rescue Puppet::Util::Json::ParseError => ex
raise ArgumentError, _("Could not parse JSON %{metadata_path}") % { metadata_path: metadata_path }, ex.backtrace
end
end
if File.file?(File.join(@path, 'Modulefile'))
Puppet.warning _("A Modulefile was found in the root directory of the module. This file will be ignored and can safely be removed.")
end
@metadata
end
def load_metadata!
@metadata = nil
metadata(true)
end
def parse_filename(filename)
match = /^((.*?)-(.*?))-(\d+\.\d+\.\d+.*?)$/.match(File.basename(filename, '.tar.gz'))
if matchView on GitHub (pinned to e227c27540)
Solutions
- Validate the file with a strict JSON parser: `ruby -rjson -e 'JSON.parse(File.read("metadata.json"))'` or `jq . metadata.json` to surface the exact line.
- Fix the reported syntax issue (remove trailing commas/comments, quote keys with double quotes, close braces).
- Remove git conflict markers after merges.
- Re-save the file as UTF-8 without BOM.
Example fix
// before
{
'name': 'acme-web', // single quotes and comment
"version": "0.1.0",
}
// after
{
"name": "acme-web",
"version": "0.1.0"
} Defensive patterns
Strategy: try-catch
Validate before calling
begin
Puppet::Util::Json.load(File.read('metadata.json'))
rescue Puppet::Util::Json::ParseError => e
abort "metadata.json is invalid: #{e.message}"
end Try / catch
begin
app.run
rescue ArgumentError => e
if e.message.include?('Could not parse JSON')
abort "fix metadata.json syntax: run `jq . metadata.json` to locate the error"
end
raise
end Prevention
- Lint metadata.json in CI with `jq empty metadata.json` or jsonlint before building modules.
- Edit JSON with editors that validate syntax; avoid hand-writing with comments/trailing commas.
- After git merges, run the jq check to catch conflict markers.
When it happens
Trigger: metadata.json containing trailing commas, single quotes, comments, unescaped newlines in strings, or a UTF-8 BOM; hand-edited JSON with a missing closing brace; a file written by a tool that emits YAML or pretty-print with smart quotes. Puppet::Util::Json (multijson-backed strict JSON) rejects it and the rescue clause re-raises as ArgumentError.
Common situations: Manually editing metadata.json and breaking syntax; merge-conflict markers left in the file from a git merge; encoding issues when editing on Windows (BOM, CRLF inside string literals); tools that write JSON5.
Related errors
- Could not %{action} '%{module_name}'; %{error}
- Parsing of 'type "%{assignment_string}"' failed with message
- The parameter '$#{name}' is invalid: #{e.message}
- %{name} has an invalid and unparsable metadata.json file. Th
- Could not find %{path} on disk
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/a5f337bae6ed1bc6.
Report an issue: GitHub.