puppetlabs/puppet · error · Puppet::Util::Windows::Error

Failed to convert binary SID

Error message

Failed to convert binary SID

What it means

Raised by Puppet::Util::Windows::SID.sid_ptr_to_string when ConvertSidToStringSidW returns FALSE, i.e. Windows failed to render the (already IsValidSid-validated) binary SID into 'S-1-...' string form. Puppet::Util::Windows::Error attaches GetLastError. Because IsValidId passed just before, this branch indicates the conversion API itself failed rather than a bad SID.

Source

Thrown at lib/puppet/util/windows/sid.rb:169

      Principal.lookup_account_sid(sid_bytes).domain_account
    rescue
      nil
    end
    module_function :sid_to_name

    # https://stackoverflow.com/a/1792930 - 68 bytes, 184 characters in a string
    MAXIMUM_SID_STRING_LENGTH = 184

    # Convert a SID pointer to a SID string, e.g. "S-1-5-32-544".
    def sid_ptr_to_string(psid)
      if !psid.is_a?(FFI::Pointer) || IsValidSid(psid) == FFI::WIN32_FALSE
        raise Puppet::Util::Windows::Error, _("Invalid SID")
      end

      sid_string = nil
      FFI::MemoryPointer.new(:pointer, 1) do |buffer_ptr|
        if ConvertSidToStringSidW(psid, buffer_ptr) == FFI::WIN32_FALSE
          raise Puppet::Util::Windows::Error, _("Failed to convert binary SID")
        end

        buffer_ptr.read_win32_local_pointer do |wide_string_ptr|
          if wide_string_ptr.null?
            raise Puppet::Error, _("ConvertSidToStringSidW failed to allocate buffer for sid")
          end

          sid_string = wide_string_ptr.read_arbitrary_wide_string_up_to(MAXIMUM_SID_STRING_LENGTH)
        end
      end

      sid_string
    end
    module_function :sid_ptr_to_string

    # Convert a SID string, e.g. "S-1-5-32-544" to a pointer (containing the
    # address of the binary SID structure). The returned value can be used in
    # Win32 APIs that expect a PSID, e.g. IsValidSid. The account for this

View on GitHub (pinned to e227c27540)

Solutions

  1. Retry the conversion once — transient allocation failures can clear.
  2. Check process memory usage / native heap health of the agent if it recurs.
  3. Confirm nothing else writes into the SID buffer between validation and conversion.
  4. Fall back to manual SDDL rendering from the SID bytes (Revision, IdentifierAuthority, SubAuthorities) if the API keeps failing.
  5. Report the Win32 code from the exception message to narrow down the API-level cause.

Example fix

// exampleFix not applicable - guard is retry-oriented, see tryCatchPattern
null
Defensive patterns

Strategy: try-catch

Try / catch

begin
  sid_string = Puppet::Util::Windows::SID.sid_ptr_to_string(ptr)
rescue Puppet::Util::Windows::Error => e
  raise unless e.code == 8 || e.code == 14 # ERROR_NOT_ENOUGH_MEMORY / ERROR_OUTOFMEMORY
  GC.start
  retry if (attempts += 1) < 2
  raise
end

Prevention

When it happens

Trigger: Heap exhaustion or process memory pressure making the API's internal LocalAlloc fail; passing a pointer to memory that was mutated between the IsValidSid check and the conversion call; running on a broken/Wine-like environment where advapi32 conversion misbehaves.

Common situations: Extremely rare in practice; occasionally seen in long-lived agents with memory fragmentation or when native memory is corrupted by another extension; test harnesses using mocked FFI modules that return WIN32_FALSE unexpectedly.

Related errors


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