puppetlabs/puppet · error · Puppet::Error

One or more file(s) specified did not exist: %{files}

Error message

One or more file(s) specified did not exist:
%{files}

What it means

`puppet parser validate file...` checks each listed manifest for existence with Puppet::FileSystem.exist?. Files that are missing are collected and, after the existing files are validated, reported together in one Puppet::Error listing every nonexistent path. Parse errors of the existing files and this missing-file error can surface in the same run.

Source

Thrown at lib/puppet/face/parser.rb:68

          manifest = Puppet.lookup(:current_environment).manifest
          files << manifest
          Puppet.notice _("No manifest specified. Validating the default manifest %{manifest}") % { manifest: manifest }
        end
      end

      missing_files = []

      files.each do |file|
        if Puppet::FileSystem.exist?(file)
          error = validate_manifest(file)
          parse_errors[file] = error if error
        else
          missing_files << file
        end
      end

      unless missing_files.empty?
        raise Puppet::Error, _("One or more file(s) specified did not exist:\n%{files}") % { files: missing_files.collect { |f| " " * 3 + f + "\n" } }
      end

      parse_errors
    end

    when_rendering :console do |errors|
      unless errors.empty?
        errors.each { |_, error| Puppet.log_exception(error) }

        exit(1)
      end

      # Prevent face_base renderer from outputting "null"
      exit(0)
    end

    when_rendering :json do |errors|
      unless errors.empty?

View on GitHub (pinned to e227c27540)

Solutions

  1. Verify each path exists before passing it (File.exist? / ls)
  2. Pre-filter globs in shell scripts, e.g. `find . -name '*.pp' -print0 | xargs -0 puppet parser validate`, instead of relying on shell expansion
  3. Run from the correct working directory or use absolute paths

Example fix

# before
puppet parser validate manifests/*.pp nonexistent.pp
# after
puppet parser validate $(ls manifests/*.pp 2>/dev/null)
Defensive patterns

Strategy: validation

Validate before calling

files = ARGV.dup
missing = files.reject { |f| File.exist?(f) }
abort "missing files:\n  #{missing.join("\n  ")}" unless missing.empty?
exit Puppet::Face[:parser, :current].validate(*files)

Try / catch

begin
  Puppet::Face[:parser, :current].validate(*files)
rescue Puppet::Error => e
  existing, missing = files.partition { |f| File.exist?(f) }
  warn e.message
  retry if !existing.empty? && missing.empty? == false && (files = existing)
end

Prevention

When it happens

Trigger: `puppet parser validate manifests/site.pp typo.pp`; passing a glob the shell did not expand (no matches, so the literal `*.pp` string is handed to Puppet); CI scripts referencing renamed or deleted manifests; running from a different working directory than the paths assume.

Common situations: Stale file lists in lint/CI pipelines; nullglob off so unmatched globs pass through literally; relative paths used from the wrong cwd.

Related errors


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