{"record":{"id":"c2cb2caf75701b8f","repo":"puppetlabs/puppet","slug":"paths-to-keyfiles-must-be-absolute-not-entry","errorCode":null,"errorMessage":"Paths to keyfiles must be absolute, not %{entry}","messagePattern":"Paths to keyfiles must be absolute, not %(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/user.rb","lineNumber":746,"sourceCode":"          the user's home directory.\"\n\n      defaultto :false\n\n      # Use Symbols instead of booleans until PUP-1967 is resolved.\n      newvalues(:true, :false)\n\n      validate do |value|\n        if [:true, :false].include? value.to_s.intern\n          return\n        end\n\n        value = [value] if value.is_a?(String)\n        if value.is_a?(Array)\n          value.each do |entry|\n            raise ArgumentError, _(\"Each entry for purge_ssh_keys must be a string, not a %{klass}\") % { klass: entry.class } unless entry.is_a?(String)\n\n            valid_home = Puppet::Util.absolute_path?(entry) || entry =~ %r{^~/|^%h/}\n            raise ArgumentError, _(\"Paths to keyfiles must be absolute, not %{entry}\") % { entry: entry } unless valid_home\n          end\n          return\n        end\n        raise ArgumentError, _(\"purge_ssh_keys must be true, false, or an array of file names, not %{value}\") % { value: value.inspect }\n      end\n\n      munge do |value|\n        # Resolve string, boolean and symbol forms of true and false to a\n        # single representation.\n        case value\n        when :false, false, \"false\"\n          []\n        when :true, true, \"true\"\n          home = homedir\n          home ? [\"#{home}/.ssh/authorized_keys\"] : []\n        else\n          # value can be a string or array - munge each value\n          [value].flatten.filter_map do |entry|","sourceCodeStart":728,"sourceCodeEnd":764,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/user.rb#L728-L764","documentation":"Raised by the validate block of the `purge_ssh_keys` property on the `user` type for each string entry that is neither an absolute path (Puppet::Util.absolute_path?, platform-aware) nor prefixed with ~/ or %h/. Puppet generates ssh_authorized_key purge resources from these paths and refuses relative ones because purging by a relative path would resolve against the agent's cwd unpredictably. %h expands to the user's home directory at munge time.","triggerScenarios":"`purge_ssh_keys => ['.ssh/authorized_keys']` or `=> ['keys/alice']`; Windows paths like 'C:Users\\\\x' missing a slash; entries built by joining without a leading slash.","commonSituations":"Shortening paths copied from ~/.ssh documentation; generating keys paths from variables that may be empty (producing '.ssh/...'); forgetting that home-relative entries must start with ~/ or %h/ exactly.","solutions":["Use an absolute path: `purge_ssh_keys => ['/etc/ssh/keys/alice/authorized_keys']`","Or a home-relative prefix: `=> ['~/.ssh/authorized_keys']` or `=> ['%h/.ssh/authorized_keys']`","Prefix generated paths explicitly: \"${home}/.ssh/authorized_keys\""],"exampleFix":"# before\nuser { 'alice':\n  ensure          => present,\n  purge_ssh_keys  => ['.ssh/id_rsa'],\n}\n\n# after\nuser { 'alice':\n  ensure          => present,\n  purge_ssh_keys  => ['~/.ssh/authorized_keys', '%h/.ssh/id_rsa'],\n}","handlingStrategy":"validation","validationCode":"require 'puppet/util'\nvalid = keys.all? { |k| Puppet::Util.absolute_path?(k) || k.start_with?('~/', '%h/') }\nraise ArgumentError, \"purge_ssh_keys paths must be absolute or ~/ or %h/ prefixed: #{keys.inspect}\" unless valid","typeGuard":"def absolute_or_home_prefixed?(entry)\n  entry.is_a?(String) && (Puppet::Util.absolute_path?(entry) || entry =~ %r{\\A(~|%h)/})\nend","tryCatchPattern":null,"preventionTips":["Standardize on '~/.ssh/authorized_keys' or '%h/.ssh/authorized_keys' for home-relative keys","Type params as Array[Stdlib::Absolutepath] where the home dir is known","Prefix generated paths explicitly with the home variable"],"tags":["puppet","user-resource","ssh-keys","path-validation"],"backgroundTag":"relative-path-rejected","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}