puppetlabs/puppet · error · Puppet::Util::Windows::Error
Failed to call GetLongPathName
Error message
Failed to call GetLongPathName
What it means
Puppet::Util::Windows::File.get_long_pathname expands a path to its long form via GetLongPathNameW: a first call sizes the buffer, a second converts, and failure of the second call raises Puppet::Util::Windows::Error. GetLongPathNameW only succeeds when every component of the path actually exists - a nonexistent path is the leading cause (code 2/3), with access-denied on intermediate directories next.
Source
Thrown at lib/puppet/util/windows/file.rb:257
def readlink(link_name)
link = nil
open_symlink(link_name) do |handle|
link = resolve_symlink(handle)
end
link
end
module_function :readlink
def get_long_pathname(path)
converted = ''.dup
FFI::Pointer.from_string_to_wide_string(path) do |path_ptr|
# includes terminating NULL
buffer_size = GetLongPathNameW(path_ptr, FFI::Pointer::NULL, 0)
FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr|
if GetLongPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE
raise Puppet::Util::Windows::Error, _("Failed to call GetLongPathName")
end
converted = converted_ptr.read_wide_string(buffer_size - 1)
end
end
converted
end
module_function :get_long_pathname
def get_short_pathname(path)
converted = ''.dup
FFI::Pointer.from_string_to_wide_string(path) do |path_ptr|
# includes terminating NULL
buffer_size = GetShortPathNameW(path_ptr, FFI::Pointer::NULL, 0)
FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr|
if GetShortPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE
raise Puppet::Util::Windows::Error, "Failed to call GetShortPathName"View on GitHub (pinned to e227c27540)
Solutions
- Verify File.exist?(path) before converting - GetLongPathName requires an existing path
- Map e.code: 2/3 missing component, 5 traversal denied, 53/1231 network share unreachable
- Create the target directory tree first, then convert
- Fall back to the original string when expansion is only cosmetic
Example fix
// before
long = Puppet::Util::Windows::File.get_long_pathname(short_path) # raises if missing
// after
long = if File.exist?(short_path)
Puppet::Util::Windows::File.get_long_pathname(short_path)
else
short_path
end Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, "#{path} must exist for long-path conversion" unless File.exist?(path)
long = Puppet::Util::Windows::File.get_long_pathname(path) Try / catch
begin long = Puppet::Util::Windows::File.get_long_pathname(path) rescue Puppet::Util::Windows::Error => e raise if e.code == 5 # access denied is a real problem long = path # 2/3: component missing - keep original end
Prevention
- Create the directory tree before expanding short names captured from ENV
- Re-check existence right before converting - paths disappear mid-run
- Treat long-path expansion as best-effort; keep the input as fallback
When it happens
Trigger: get_long_pathname(path) where path (or any parent) does not currently exist; the path is a network share whose server is unreachable; a parent directory denies traversal (5); the path is already long-form but contains wildcard/invalid characters.
Common situations: Expanding 8.3 short names (e.g. PROGRA~1, from legacy installers or ENV['TEMP']) for directories created later in the run; converting paths captured before a package uninstall removed them; concurrent deletion racing the conversion.
Related errors
- ReplaceFile(#{target}, #{source})
- MoveFileEx(#{source}, #{target}, #{flags.to_s(8)})
- GetFileAttributes(#{file_name})
- Failed to set file attributes
- CreateFile(#{file_name}, #{desired_access.to_s(8)}, #{share_
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/039830c13b5b5327.
Report an issue: GitHub.