{"record":{"id":"71a4b5ce031e9ed6","repo":"puppetlabs/puppet","slug":"one-or-more-file-s-specified-did-not-exist-fil","errorCode":null,"errorMessage":"One or more file(s) specified did not exist:\n%{files}","messagePattern":"One or more file\\(s\\) specified did not exist:\n%(.+?)","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/face/parser.rb","lineNumber":68,"sourceCode":"          manifest = Puppet.lookup(:current_environment).manifest\n          files << manifest\n          Puppet.notice _(\"No manifest specified. Validating the default manifest %{manifest}\") % { manifest: manifest }\n        end\n      end\n\n      missing_files = []\n\n      files.each do |file|\n        if Puppet::FileSystem.exist?(file)\n          error = validate_manifest(file)\n          parse_errors[file] = error if error\n        else\n          missing_files << file\n        end\n      end\n\n      unless missing_files.empty?\n        raise Puppet::Error, _(\"One or more file(s) specified did not exist:\\n%{files}\") % { files: missing_files.collect { |f| \" \" * 3 + f + \"\\n\" } }\n      end\n\n      parse_errors\n    end\n\n    when_rendering :console do |errors|\n      unless errors.empty?\n        errors.each { |_, error| Puppet.log_exception(error) }\n\n        exit(1)\n      end\n\n      # Prevent face_base renderer from outputting \"null\"\n      exit(0)\n    end\n\n    when_rendering :json do |errors|\n      unless errors.empty?","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/face/parser.rb#L50-L86","documentation":"`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.","triggerScenarios":"`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.","commonSituations":"Stale file lists in lint/CI pipelines; nullglob off so unmatched globs pass through literally; relative paths used from the wrong cwd.","solutions":["Verify each path exists before passing it (File.exist? / ls)","Pre-filter globs in shell scripts, e.g. `find . -name '*.pp' -print0 | xargs -0 puppet parser validate`, instead of relying on shell expansion","Run from the correct working directory or use absolute paths"],"exampleFix":"# before\npuppet parser validate manifests/*.pp nonexistent.pp\n# after\npuppet parser validate $(ls manifests/*.pp 2>/dev/null)","handlingStrategy":"validation","validationCode":"files = ARGV.dup\nmissing = files.reject { |f| File.exist?(f) }\nabort \"missing files:\\n  #{missing.join(\"\\n  \")}\" unless missing.empty?\nexit Puppet::Face[:parser, :current].validate(*files)","typeGuard":null,"tryCatchPattern":"begin\n  Puppet::Face[:parser, :current].validate(*files)\nrescue Puppet::Error => e\n  existing, missing = files.partition { |f| File.exist?(f) }\n  warn e.message\n  retry if !existing.empty? && missing.empty? == false && (files = existing)\nend","preventionTips":["Pre-filter file lists with File.exist? before handing them to the parser face","Expand globs yourself (Dir.glob) instead of relying on shell expansion with nullglob off"],"tags":["puppet","parser","cli","file-not-found","validation"],"backgroundTag":"file-not-found","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}