puppetlabs/puppet · error · Puppet::Error
Could not read JSON data for %{name} %{key}: %{detail}
Error message
Could not read JSON data for %{name} %{key}: %{detail} What it means
load_json_from_file reads the stored .json file in binary mode; Errno::ENOENT returns nil (a cache miss), but any other failure - EACCES, EISDIR, EMFILE, EIO - is wrapped as Puppet::Error 'Could not read JSON data for <indirection> <key>: <detail>' with the original backtrace.
Source
Thrown at lib/puppet/indirector/json.rb:65
base = data_dir
File.join(base, self.class.indirection_name.to_s, name.to_s + ext)
end
private
def data_dir
Puppet.run_mode.server? ? Puppet[:server_datadir] : Puppet[:client_datadir]
end
def load_json_from_file(file, key)
json = nil
begin
json = Puppet::FileSystem.read(file, :encoding => Encoding::BINARY)
rescue Errno::ENOENT
return nil
rescue => detail
raise Puppet::Error, _("Could not read JSON data for %{name} %{key}: %{detail}") % { name: indirection.name, key: key, detail: detail }, detail.backtrace
end
begin
from_json(json)
rescue => detail
raise Puppet::Error, _("Could not parse JSON data for %{name} %{key}: %{detail}") % { name: indirection.name, key: key, detail: detail }, detail.backtrace
end
end
def from_json(text)
model.convert_from('json', text.force_encoding(Encoding::UTF_8))
end
def to_json(object)
object.render('json')
end
end
View on GitHub (pinned to e227c27540)
Solutions
- Read the <detail> suffix to identify the errno, then reproduce as the service user (sudo -u puppet cat <file>).
- chown/chmod the file and its parent directory to the puppet service user.
- Remove or rename the directory sitting at the file path so Puppet can recreate the file.
- Raise ulimit / fix fd leaks if the detail says 'too many open files'.
Example fix
# before # Could not read JSON data for node node1.example.com: Permission denied @ rb_sysopen # after chown puppet:puppet /opt/puppetlabs/server/data/puppet/node/node1.example.com.json chmod 660 /opt/puppetlabs/server/data/puppet/node/node1.example.com.json
Defensive patterns
Strategy: try-catch
Validate before calling
file = store_path_for(key) raise ArgumentError, 'unreadable store file' unless File.readable?(file) indirection.find(key)
Try / catch
begin Puppet::Node.indirection.find(key) rescue Puppet::Error => e Puppet.err(e.message) nil end
Prevention
- Keep datadir ownership uniform under the service user.
- Monitor server logs for EACCES on datadir paths.
- Exclude datadirs from backup tooling that recreates files as directories.
When it happens
Trigger: find/search on a json-backed indirection when the stored file exists but is unreadable by the service user, the path has been replaced by a directory, or the process ran out of file descriptors.
Common situations: Datadir files left 600/root after a restore or manual copy; backup jobs recreating paths as directories; long-running masters hitting fd limits; SELinux context changes.
Related errors
- Could not destroy %{json} %{request}: %{detail}
- Could not destroy %{name} %{request}: %{detail}
- Could not back up %{file}: %{detail}
- %{path} is not readable
- invalid key
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/f023df31e345cf63.
Report an issue: GitHub.