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

Failed to load user profile %{user}

Error message

Failed to load user profile %{user}

What it means

Raised by Puppet::Util::Windows::User.load_profile when LoadUserProfileW returns FALSE after a successful LogonUserW. The method logs on as the user (with PI_NOUI set to suppress profile error dialogs) to create/load the profile and then unload it. Puppet::Util::Windows::Error attaches the Win32 reason — typical codes are ERROR_ACCESS_DENIED (not elevated / profile store off-limits) and errors from a corrupt or locked ntuser.dat.

Source

Thrown at lib/puppet/util/windows/user.rb:133

  module_function :logon_user

  def self.logon_user_by_logon_type(name, domain, password, logon_type, logon_provider, token)
    LogonUserW(wide_string(name), wide_string(domain), password.nil? ? FFI::Pointer::NULL : wide_string(password), logon_type, logon_provider, token)
  end

  private_class_method :logon_user_by_logon_type

  def load_profile(user, password)
    logon_user(user, password) do |token|
      FFI::MemoryPointer.from_string_to_wide_string(user) do |lpUserName|
        pi = PROFILEINFO.new
        pi[:dwSize] = PROFILEINFO.size
        pi[:dwFlags] = 1 # PI_NOUI - prevents display of profile error msgs
        pi[:lpUserName] = lpUserName

        # Load the profile. Since it doesn't exist, it will be created
        if LoadUserProfileW(token, pi.pointer) == FFI::WIN32_FALSE
          raise Puppet::Util::Windows::Error, _("Failed to load user profile %{user}") % { user: user.inspect }
        end

        Puppet.debug("Loaded profile for #{user}")

        if UnloadUserProfile(token, pi[:hProfile]) == FFI::WIN32_FALSE
          raise Puppet::Util::Windows::Error, _("Failed to unload user profile %{user}") % { user: user.inspect }
        end
      end
    end
  end
  module_function :load_profile

  def get_rights(name)
    user_info = Puppet::Util::Windows::SID.name_to_principal(name.sub(/^\.\\/, "#{Puppet::Util::Windows::ADSI.computer_name}\\"))
    return "" unless user_info

    rights = []
    rights_pointer = FFI::MemoryPointer.new(:pointer)

View on GitHub (pinned to e227c27540)

Solutions

  1. Run elevated — LoadUserProfileW typically requires administrator privileges for other users' profiles.
  2. Check the Win32 code in the exception and the Application log (ProfSvc / User Profile Service events) for the specific failure.
  3. If the hive is stale-locked, unload it (or reboot) and delete leftover temp profiles before retrying.
  4. Verify the profile path exists or is creatable (roaming share reachable, quota/disk space available).
  5. Re-run Puppet after fixing; profile creation is usually idempotent once the blocker is removed.

Example fix

# before
Puppet::Util::Windows::User.load_profile(user, password)

# after - surface profile-service context on failure
begin
  Puppet::Util::Windows::User.load_profile(user, password)
rescue Puppet::Util::Windows::Error => e
  Puppet.err("Profile load for #{user} failed (Win32 #{e.code}); check ProfSvc events in the Application log")
  raise
end
Defensive patterns

Strategy: try-catch

Validate before calling

# cheap pre-checks: user exists and profile service is running
raise 'ProfSvc not running' unless `sc query ProfSvc` =~ /RUNNING/
raise 'no such user' unless Puppet::Util::Windows::SID.name_to_principal(user)

Try / catch

begin
  Puppet::Util::Windows::User.load_profile(user, password)
rescue Puppet::Util::Windows::Error => e
  raise unless e.message.include?('Failed to load user profile')
  raise 'load_profile requires an elevated process' if e.code == 5
  raise "profile issue (Win32 #{e.code}); check User Profile Service events"
end

Prevention

When it happens

Trigger: Loading a profile while the process is not elevated; the user's registry hive (ntuser.dat) is locked by another process or corrupt; profile service (ProfSvc) issues; the profile path pointing to an unavailable location (roaming profile share down); disk full preventing profile creation.

Common situations: Puppet creating local users and immediately loading profiles in the same run on machines where the agent runs non-elevated; roaming profiles on an unreachable share; a previous run crashed leaving the hive loaded (temp profile accumulation); profile list in the registry referencing deleted directories.

Related errors


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