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

Failed to logon user %{name}

Error message

Failed to logon user %{name}

What it means

Raised by Puppet::Util::Windows::User.logon_user when LogonUserW fails in both NETWORK (fLOGON32_LOGON_NETWORK) and INTERACTIVE (fLOGON32_LOGON_INTERACTIVE) logon types — the code tries network first and falls back to interactive before giving up. The message embeds name.inspect and Puppet::Util::Windows::Error appends the Win32 reason. The module also defines logon-specific codes (ERROR_ACCOUNT_RESTRICTION 1327, ERROR_INVALID_LOGON_HOURS 1328, ERROR_INVALID_WORKSTATION 1329, ERROR_ACCOUNT_DISABLED 1331) which password_is? interprets as 'wrong password'.

Source

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

      ERROR_ACCOUNT_DISABLED,
    ]

    authenticated_error_codes.include?(detail.code)
  end
  module_function :password_is?

  def logon_user(name, password, domain = '.', &block)
    fLOGON32_PROVIDER_DEFAULT = 0
    fLOGON32_LOGON_INTERACTIVE = 2
    fLOGON32_LOGON_NETWORK = 3

    token = nil
    begin
      FFI::MemoryPointer.new(:handle, 1) do |token_pointer|
        # try logon using network else try logon using interactive mode
        if logon_user_by_logon_type(name, domain, password, fLOGON32_LOGON_NETWORK, fLOGON32_PROVIDER_DEFAULT, token_pointer) == FFI::WIN32_FALSE
          if logon_user_by_logon_type(name, domain, password, fLOGON32_LOGON_INTERACTIVE, fLOGON32_PROVIDER_DEFAULT, token_pointer) == FFI::WIN32_FALSE
            raise Puppet::Util::Windows::Error, _("Failed to logon user %{name}") % { name: name.inspect }
          end
        end

        yield token = token_pointer.read_handle
      end
    ensure
      FFI::WIN32.CloseHandle(token) if token
    end

    # token has been closed by this point
    true
  end
  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

View on GitHub (pinned to e227c27540)

Solutions

  1. Verify the credentials manually: `runas /user:<domain>\<name> cmd` or PowerShell to confirm the password works.
  2. Check the Win32 code in the error (e.code): 1326 bad password, 1331 disabled, 1327/1328/1329 policy restrictions, 1385 missing logon right.
  3. Fix escaping of special characters in the manifest password (quotes, backslashes, $).
  4. Grant the needed logon right (e.g. SeServiceLogonRight / SeInteractiveLogonRight) via user_rights management or Local Security Policy.
  5. Confirm the domain argument: '.' for local accounts, correct NETBIOS/FQDN for domain accounts.

Example fix

# before
Puppet::Util::Windows::User.logon_user(name, password) { |token| ... } # raises on bad creds

# after - classify the failure instead of a generic crash
begin
  Puppet::Util::Windows::User.logon_user(name, password) { |token| ... }
rescue Puppet::Util::Windows::Error => e
  case e.code
  when 1326 then raise ArgumentError, 'invalid credentials'
  when 1331 then raise ArgumentError, 'account disabled'
  else raise
  end
end
Defensive patterns

Strategy: try-catch

Validate before calling

# pre-flight the credentials before logon-dependent work
# (cheap check: resolve the account, then rely on one controlled attempt)
principal = Puppet::Util::Windows::SID.name_to_principal("#{domain}\\#{name}")
raise ArgumentError, "account #{name} does not exist" unless principal

Try / catch

begin
  Puppet::Util::Windows::User.logon_user(name, password, domain) { |t| ... }
rescue Puppet::Util::Windows::Error => e
  case e.code
  when 1326 then raise ArgumentError, 'bad username or password'
  when 1327, 1328, 1329, 1331 then raise ArgumentError, "account restriction: Win32 #{e.code}"
  when 1385 then raise 'grant SeInteractiveLogonRight/SeServiceLogonRight first'
  else raise
  end
end

Prevention

When it happens

Trigger: Wrong username/password (ERROR_LOGON_FAILURE 1326); account disabled (1331); restricted logon hours (1328); workstation restriction (1329); expired password; missing 'Log on as a batch/service' right (ERROR_LOGON_TYPE_NOT_GRANTED 1385) for the interactive fallback; machine account vs domain account confusion in the domain argument.

Common situations: User resource with an invalid password in the manifest (typo, special-character escaping); managing a domain user while the DC rejects the credentials; accounts created by Puppet that are disabled by policy; password contains characters mangled by manifest escaping; user lacks rights when Puppet later calls LogonUser to load the profile.

Related errors


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