puppetlabs/puppet · error · ArgumentError

%{path} is not readable

Error message

%{path} is not readable

What it means

The second check in Mount::File#path=: after confirming the directory exists, FileTest.readable? must pass for the process loading the config. A missing execute/search or read permission on the served directory makes the mount unusable and raises ArgumentError.

Source

Thrown at lib/puppet/file_serving/mount/file.rb:58

  # Return the path as appropriate, expanding as necessary.
  def path(node = nil)
    if expandable?
      expand(@path, node)
    else
      @path
    end
  end

  # Set the path.
  def path=(path)
    # FIXME: For now, just don't validate paths with replacement
    # patterns in them.
    if path =~ /%./
      # Mark that we're expandable.
      @expandable = true
    else
      raise ArgumentError, _("%{path} does not exist or is not a directory") % { path: path } unless FileTest.directory?(path)
      raise ArgumentError, _("%{path} is not readable") % { path: path } unless FileTest.readable?(path)

      @expandable = false
    end
    @path = path
  end

  def search(path, request)
    path = complete_path(path, request.node)
    return nil unless path

    [path]
  end

  # Verify our configuration is valid.  This should really check to
  # make sure at least someone will be allowed, but, eh.
  def validate
    raise ArgumentError, _("Mounts without paths are not usable") if @path.nil?
  end

View on GitHub (pinned to e227c27540)

Solutions

  1. Identify the user the file server runs as, then grant traversal/read: `chmod o+rx /srv/data` or `chown -R puppet: /srv/data` as appropriate
  2. For SELinux, restore the correct context (restorecon / semanage fcontext) on the served path
  3. Verify as the service user: `sudo -u puppet test -r /srv/data && echo ok`

Example fix

# before
# /srv/data owned root:600, puppetserver runs as 'puppet'
[data]
  path /srv/data

# after (shell)
sudo chown -R puppet: /srv/data
sudo chmod -R u+rX /srv/data
# fileserver.conf stays the same
Defensive patterns

Strategy: validation

Validate before calling

def readable_by?(user, dir)
  system("sudo -u #{user} test -r #{Shellwords.escape(dir)}")
end

fail "#{dir} not readable by puppet" unless readable_by?('puppet', dir)

Try / catch

begin
  mount.path = dir
rescue ArgumentError => e
  raise unless e.message.end_with?('is not readable')
  raise "fix permissions on #{dir} for the service user, then redeploy"
end

Prevention

When it happens

Trigger: The served directory is owned root:0600 (or lacks o+x) while puppet/puppetserver runs as the `puppet` user; SELinux or AppArmor denials on the path; a mount path on storage with restrictive ACLs.

Common situations: Directories created by root scripts with umask 077; puppetserver running as a dedicated user after previously running as root; SELinux enforcing on EL systems with non-standard content paths.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/97573b9da94dbe06. Report an issue: GitHub.