{"record":{"id":"5c25f0df1d5f72cb","repo":"puppetlabs/puppet","slug":"fileset-paths-must-be-fully-qualified-path","errorCode":null,"errorMessage":"Fileset paths must be fully qualified: %{path}","messagePattern":"Fileset paths must be fully qualified: %(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/file_serving/fileset.rb","lineNumber":36,"sourceCode":"    result = {}\n\n    filesets.each do |fileset|\n      fileset.files.each do |file|\n        result[file] ||= fileset.path\n      end\n    end\n\n    result\n  end\n\n  def initialize(path, options = {})\n    if Puppet::Util::Platform.windows?\n      # REMIND: UNC path\n      path = path.chomp(File::SEPARATOR) unless path =~ %r{^[A-Za-z]:/$}\n    else\n      path = path.chomp(File::SEPARATOR) unless path == File::SEPARATOR\n    end\n    raise ArgumentError, _(\"Fileset paths must be fully qualified: %{path}\") % { path: path } unless Puppet::Util.absolute_path?(path)\n\n    @path = path\n\n    # Set our defaults.\n    self.ignore = []\n    self.links = :manage\n    @recurse = false\n    @recurselimit = :infinite\n    @max_files = 0\n\n    if options.is_a?(Puppet::Indirector::Request)\n      initialize_from_request(options)\n    else\n      initialize_from_hash(options)\n    end\n\n    raise ArgumentError, _(\"Fileset paths must exist\") unless valid?(path)\n    # TRANSLATORS \"recurse\" and \"recurselimit\" are parameter names and should not be translated","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/file_serving/fileset.rb#L18-L54","documentation":"Puppet::FileServing::Fileset#initialize chomps a trailing separator (special-casing Windows drive roots like `C:/`) and then requires Puppet::Util.absolute_path?(path) to be true. Relative paths cannot be resolved against a well-known base, so the constructor raises ArgumentError before any options are applied.","triggerScenarios":"Calling Puppet::FileServing::Fileset.new('modules/foo', ...) or Fileset.new('relative/dir') with a path that has no leading `/` (or drive letter on Windows); building a fileset from user-supplied or interpolated strings that were never expanded.","commonSituations":"Scripts that construct filesets from relative paths assuming the process cwd; porting Unix code to Windows where the path lacks a drive letter; options hashes deserialized from requests where the path lost its leading slash.","solutions":["Expand the path before constructing: File.expand_path(p) (or File.join(base_dir, p)) so it becomes absolute","On Windows, make sure the path includes the drive letter (e.g. `C:/srv/data`)","Validate inputs at the boundary of your tooling with Puppet::Util.absolute_path? and reject/normalize relative paths early"],"exampleFix":"# before\nfileset = Puppet::FileServing::Fileset.new('modules/foo', recurse: true)\n\n# after\nfileset = Puppet::FileServing::Fileset.new(File.expand_path('modules/foo'), recurse: true)","handlingStrategy":"validation","validationCode":"def fileset_path!(p)\n  raise ArgumentError, \"relative path: #{p}\" unless Puppet::Util.absolute_path?(p)\n  p\nend\n\npath = fileset_path!(user_supplied_path)\nfileset = Puppet::FileServing::Fileset.new(path, options)","typeGuard":"# Narrow arbitrary input to an absolute path String before use\ndef absolute_path_string?(v)\n  v.is_a?(String) && Puppet::Util.absolute_path?(v)\nend","tryCatchPattern":"begin\n  Puppet::FileServing::Fileset.new(path, options)\nrescue ArgumentError => e\n  raise unless e.message.start_with?('Fileset paths must be fully qualified')\n  retry_with = File.expand_path(path) # or log & reject\nend","preventionTips":["Call File.expand_path at the system boundary where strings enter your code","Never build filesets from cwd-relative constants","On Windows, include the drive letter and prefer forward slashes"],"tags":["puppet","fileset","path-validation","argumenterror","ruby"],"backgroundTag":"path-validation-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}