If Kerberos worked yesterday and fails today, you probably didn’t break anything. Microsoft changed the defaults underneath you. Windows Server 2025 domain controllers are AES-first and, per Microsoft’s phased rollout, don’t issue RC4-encrypted TGTs by default. The CVE-2026-20833 hardening moved RC4 handling through its enforcement phases during 2026, and NTLM is on a published path to being disabled by default. Setups that quietly relied on RC4 or NTLM fallback now fail loudly.
This guide has one rule: prove the cause before you change anything. You’ll use klist, setspn, and specific Event IDs to separate SPN, time-skew, and encryption-type problems. Then you apply the narrowest fix.
Prerequisites
- Domain controllers: At least one Windows Server 2025 DC. Mixed domains with Windows Server 2019/2022 DCs are covered too.
- Admin rights: Local admin on the client and target server. Domain Admin, or delegated rights, to read and modify SPNs and
msDS-SupportedEncryptionTypes. - Tools:
klist,w32tm,nltest, and Event Viewer are built into Windows.setspnis on domain controllers and comes with the RSAT AD DS tools, so run it from a DC or a management host with RSAT installed. The PowerShell examples need the ActiveDirectory module:Install-WindowsFeature RSAT-AD-PowerShellon Windows Server, orAdd-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0on Windows 10/11. - Audit policy: Kerberos auditing must be on for the DCs, or events 4768/4769 won’t be logged. Step 3 of Quick Diagnosis shows how.
- An elevated prompt: Several commands, including
klist -li 0x3e7, fail silently or return “access denied” without elevation.
Example Environment
The examples use a sample domain, contoso.com, with Windows Server 2025 domain controllers, one Windows Server 2022 DC, a Windows 11 24H2 client, a SQL Server 2022 member server, and a Linux web app that uses a keytab. Sample output is illustrative: names, timestamps, and field layout can differ on your systems.
How Kerberos Fails: The 60-Second Refresher
You only need enough protocol knowledge to read the errors. Kerberos has three exchanges, and each one fails in its own way:
| Exchange | What happens | Who logs it | Typical errors |
|---|---|---|---|
| AS-REQ / AS-REP | Client proves who it is and gets a TGT (Ticket Granting Ticket) | DC, Security 4768 / 4771 | KDC_ERR_PREAUTH_FAILED, KDC_ERR_ETYPE_NOSUPP, KRB_AP_ERR_SKEW |
| TGS-REQ / TGS-REP | Client shows its TGT and asks for a ticket to a specific SPN | DC, Security 4769 | KDC_ERR_S_PRINCIPAL_UNKNOWN, KDC_ERR_ETYPE_NOSUPP |
| AP-REQ / AP-REP | Client hands the service ticket to the target service | Target server, System log (Security-Kerberos) | KRB_AP_ERR_MODIFIED, KRB_AP_ERR_SKEW |
The key point: the DC encrypts the service ticket with the key of whichever account owns the SPN. If the service runs as a different account, or two accounts claim the same SPN, the service can’t decrypt the ticket. That’s KRB_AP_ERR_MODIFIED. The DC did its job; the SPN mapping is what’s wrong.
The five errors you’ll actually see:
KDC_ERR_S_PRINCIPAL_UNKNOWN(0x7): The DC couldn’t find any account with that SPN. The SPN is missing, or the client asked for the wrong name.KDC_ERR_ETYPE_NOSUPP(0xE): The client, the account, and the DC share no encryption type. After the 2026 changes, this usually means RC4-only.KRB_AP_ERR_SKEW(0x25): The clocks are more than 5 minutes apart. That’s the default tolerance.KRB_AP_ERR_MODIFIED(0x29): The service couldn’t decrypt the ticket. Usually a duplicate or misassigned SPN, or a stale password or keytab.KDC_ERR_PREAUTH_FAILED(0x18): Wrong password during pre-authentication. Often a stale credential saved in a service, scheduled task, or mapped drive.
Quick Diagnosis: Run These First
Before you touch any setting, collect evidence from the client, the target server, and the DC involved.
1. Find which DC the client is using
nltest /dsgetdc:contoso.com
Expected output (trimmed):
DC: \\DC01.contoso.com
Address: \\10.0.10.10
Dom Name: contoso.com
Flags: PDC GC DS LDAP KDC TIMESERV GTIMESERV WRITABLE DNS_DC DNS_DOMAIN DNS_FOREST CLOSE_SITE FULL_SECRET WS DS_8 DS_9 DS_10 KEYLIST DS_13
The command completed successfully
Check the Security log on that DC. It’s easy to lose an hour reading logs on the wrong one.
2. Reproduce the failure cleanly
Flush the caches so you see a fresh request instead of a cached ticket:
ipconfig /flushdns
nbtstat -RR
klist purge
# -li 0x3e7 targets the Local System logon session (the computer account's tickets).
# Services running as a user account or gMSA keep their own tickets: restart those services instead.
klist -li 0x3e7 purge
Now reproduce the failure: open the share, connect to SQL, or load the web app. Note the exact time so you can match it to events.
3. Make sure Kerberos auditing is on (DCs)
auditpol /get /subcategory:"Kerberos Authentication Service"
auditpol /get /subcategory:"Kerberos Service Ticket Operations"
If either line shows No Auditing, enable both through your DC GPO (Computer Configuration > Policies > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Account Logon). For a quick test on one DC, run:
auditpol /set /subcategory:"Kerberos Authentication Service" /success:enable /failure:enable
auditpol /set /subcategory:"Kerberos Service Ticket Operations" /success:enable /failure:enable
Warning: Success auditing for Kerberos Service Ticket Operations is noisy on busy DCs. Size the Security log to at least 1 GB on DCs, or forward events to a SIEM. Otherwise the event you need will roll off within minutes.
4. Ask for the ticket directly
klist get requests a service ticket for a specific SPN. It shows the KDC’s error without any application in the way:
klist get MSSQLSvc/sql01.contoso.com:1433
On success, the new ticket shows up in the cache. On failure you get the raw error, for example 0x80090311 or KDC_ERR_S_PRINCIPAL_UNKNOWN. A successful klist get proves the client can get a ticket for that SPN from the KDC. It doesn’t prove the application uses Kerberos, asks for the same name, or can validate the ticket. For that, check the target’s 4624 events (Authentication Package) and the application’s own logs.
5. Read what’s cached
klist
Current LogonId is 0:0x5a3c1
Cached Tickets: (2)
#0> Client: jdoe @ CONTOSO.COM
Server: krbtgt/CONTOSO.COM @ CONTOSO.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 9/25/2026 8:02:11 (local)
End Time: 9/25/2026 18:02:11 (local)
Renew Time: 10/2/2026 8:02:11 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
Kdc Called: DC01.contoso.com#1> Client: jdoe @ CONTOSO.COM
Server: cifs/fs01.contoso.com @ CONTOSO.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
…
Kdc Called: DC01.contoso.com
Check three fields: Server (is the SPN what you expected?), KerbTicket Encryption Type (AES or RC4?), and Kdc Called (which DC issued it?). A TGT with no service ticket for the target means the client never asked, or the request failed. Go to the DC’s 4769 events next.
Reading the Logs: 4768, 4769, 4771, and Event ID 4
Security events on the DC
Open Event Viewer > Windows Logs > Security on the DC that nltest returned. Filter on these IDs:
| Event ID | Meaning | Key fields |
|---|---|---|
| 4768 | TGT requested (AS-REQ) | Account Name, Result Code, Ticket Encryption Type, Client Address |
| 4769 | Service ticket requested (TGS-REQ) | Service Name, Failure Code, Ticket Encryption Type |
| 4771 | Kerberos pre-authentication failed | Failure Code (0x18 = bad password), Client Address |
Ticket Encryption Type values:
| Value | Type | Status in 2026 |
|---|---|---|
0x11 | AES128-CTS-HMAC-SHA1-96 | Good |
0x12 | AES256-CTS-HMAC-SHA1-96 | Good (preferred) |
0x17 | RC4-HMAC | Being removed; find these |
0x18 | RC4-HMAC-EXP | Legacy; find these |
0x1 / 0x3 | DES | Disabled by default since Windows 7 / Server 2008 R2 |
0xffffffff | Request failed | Look at the failure code |
On DCs with the 2026 updates, 4768 and 4769 carry extra encryption-type detail. You get the account’s supported types, the keys that actually exist for the account, and what the client advertised. If your events show these fields, they’re the fastest proof of an RC4 problem. The Detect and remediate RC4 usage in Kerberos page documents them, along with the KDCSVC System-log events for RC4 auditing. Treat that page as the source of truth for exact Event IDs. Blog posts drift, this one included.
In a busy log, PowerShell is a better starting point than scrolling. First check the field names and value format your DC actually writes:
# Print the EventData fields of the most recent 4769 on this DC
([xml](Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4769)]]" -MaxEvents 1).ToXml()).Event.EventData.Data |
Format-Table Name, '#text' -AutoSize
If the fields match, this lists recent service tickets issued with RC4:
# Find the last 50 service tickets issued with RC4 (0x17) on this DC
Get-WinEvent -LogName Security -MaxEvents 50 -FilterXPath "*[System[(EventID=4769)] and EventData[Data[@Name='TicketEncryptionType']='0x17']]" |
ForEach-Object {
$x = [xml]$_.ToXml()
[pscustomobject]@{
Time = $_.TimeCreated
Account = ($x.Event.EventData.Data | Where-Object Name -eq 'TargetUserName').'#text'
Service = ($x.Event.EventData.Data | Where-Object Name -eq 'ServiceName').'#text'
Client = ($x.Event.EventData.Data | Where-Object Name -eq 'IpAddress').'#text'
}
} | Format-Table -AutoSize
For failures, use a separate query: Data[@Name='Status']='0x7' for missing-SPN failures, or '0xe' for encryption-type failures. Those only match failed 4769 events (Audit Failure), not successful tickets. Field names and value formatting can vary between builds, so confirm both with the command above or one event’s Details > XML View. An empty result doesn’t prove there’s no RC4 or no failure. It can just mean the filter doesn’t match your schema.
Event ID 4 (KRB_AP_ERR_MODIFIED) on the target or client
This one lives in the System log. Look in Windows Logs > System for source Security-Kerberos, Event ID 4, on the machine that received the ticket (and sometimes on the client):
The Kerberos client received a KRB_AP_ERR_MODIFIED error from the server sql01$.
The target name used was MSSQLSvc/sql01.contoso.com:1433. This indicates that the
target server failed to decrypt the ticket provided by the client. This can occur
when the target server principal name (SPN) is registered on an account other than
the account the target service is using.
Handily, the message names the SPN. Event ID 4 isn’t proof of an SPN problem on its own, though. Microsoft’s troubleshooting guidance lists clock skew as well as a non-unique SPN among its causes, and a stale password or keytab produces it too. Rule out time first, then take the SPN to setspn -Q.
Common Issues and Solutions
Problem: KRB_AP_ERR_MODIFIED (Duplicate or Misassigned SPN)
Symptoms:
- System log Event ID 4 with
KRB_AP_ERR_MODIFIEDon the client or service host - Users get a credential prompt, or the app logs “The target principal name is incorrect”
klistshows a service ticket was issued, yet the connection still fails
Why it happens: Microsoft lists two top causes: clock skew, and an SPN that isn’t unique. The DC finds the SPN on account A and encrypts the ticket with A’s key. The service runs as account B, so it can’t decrypt the ticket. A classic trigger is moving SQL Server from LocalSystem to a domain service account without moving the SPN. A stale password does the same thing, such as a keytab generated before a password reset.
Fix:
- Rule out time first. See the time skew section below. It takes 30 seconds.
- Find who owns the SPN:
setspn -Q MSSQLSvc/sql01.contoso.com:1433
Checking domain DC=contoso,DC=com
CN=SQL01,OU=Servers,DC=contoso,DC=com
MSSQLSvc/sql01.contoso.com:1433
TERMSRV/SQL01
RestrictedKrbHost/SQL01
HOST/SQL01
…Existing SPN found!
- Scan the domain for duplicates. Add
-F(setspn -X -F) to search at forest scope. Results reflect what the DC you query can see and what you’re allowed to read, so allow for replication delay, and check trusted forests separately if the duplicate could live there:
setspn -X
Checking domain DC=contoso,DC=com
Processing entry 0
MSSQLSvc/sql01.contoso.com:1433 is registered on these accounts:
CN=svc_sql,OU=Service Accounts,DC=contoso,DC=com
CN=SQL01,OU=Servers,DC=contoso,DC=comfound 1 group of duplicate SPNs.
- Check which account the service actually runs as:
Get-CimInstance Win32_Service -Filter "Name='MSSQLSERVER'" | Select-Object Name, StartName
Name StartName
—- ———
MSSQLSERVER CONTOSO\svc_sql
This example assumes a default SQL Server instance on TCP 1433. Named instances, dynamic ports, and Always On listeners use different SPNs and service names, so check those against Microsoft’s SQL Server SPN guidance.
- Remove the SPN from the wrong account, then confirm it exists only on the right one:
# -D deletes the SPN from the named account; this removes it from the computer object
setspn -D MSSQLSvc/sql01.contoso.com:1433 SQL01
# -S adds the SPN only after checking the domain for duplicates (always use -S, never -A)
setspn -S MSSQLSvc/sql01.contoso.com:1433 CONTOSO\svc_sql
Warning: Don’t delete
HOST/orRestrictedKrbHost/SPNs from computer objects. Those belong there. Removing them breaks SMB, remote management, and Group Policy for that machine. Only move the application-specific SPN.
Verify: Wait for AD replication, or force it with repadmin /syncall /AdeP in a lab. Then purge and retest from the client:
klist purge
klist get MSSQLSvc/sql01.contoso.com:1433
The ticket should appear, and the Event ID 4 errors should stop.
Tip: If the “duplicate” is really a keytab problem (Linux or Java services), regenerate the keytab after any password reset on that account. An old keytab holds the old key, which produces the same KRB_AP_ERR_MODIFIED error.
Problem: KDC_ERR_S_PRINCIPAL_UNKNOWN (Missing SPN, or Connecting by IP/CNAME)
Symptoms:
- DC Security log shows 4769 with Failure Code
0x7 klist getreturnsKDC_ERR_S_PRINCIPAL_UNKNOWN- Works with
\\fs01.contoso.com, fails (or falls back to NTLM) with\\10.0.20.15or\\files.contoso.com
Why it happens: The client builds the SPN from the name you typed. Connect with an alias like files.contoso.com, and it asks for cifs/files.contoso.com. No account has that SPN. Connect by IP, and Windows won’t even try Kerberos by default. You get NTLM and no error. That silent fallback is worse, and the NTLM section covers it.
Fix:
- Confirm the SPN is missing:
setspn -Q HTTP/intranet.contoso.com
Checking domain DC=contoso,DC=com
No such SPN found.
- Register the SPN on the account the service actually runs as. For IIS with a custom app pool identity, that’s the pool account:
setspn -S HTTP/intranet.contoso.com CONTOSO\svc_intranet
setspn -S HTTP/intranet CONTOSO\svc_intranet
- For a CNAME alias on a standalone file server whose shares run as the computer account, add the alias as an alternate computer name instead of adding SPNs by hand:
# Adds files.contoso.com as an alternate computer name: updates the computer object's
# alternate DNS names and HOST SPNs in AD, and registers the name in DNS if dynamic updates are allowed
netdom computername fs01.contoso.com /add:files.contoso.com
Use this only for services that run as the computer account, such as SMB file shares on a standalone server. Clustered roles, IIS, SQL Server, delegated authentication, and anything running under a gMSA or user account need their own documented SPN and delegation steps. In most of those cases you register the alias SPN on the service account instead, as in step 2.
- For IP-based connections, the right fix is to use the DNS name. Windows can request IP-address SPNs if you enable the
TryIPSPNclient setting and register the IP as an SPN. It’s fragile, though. The SPN breaks whenever the IP changes. Keep it as a last resort for hard-coded legacy clients, and confirm the client OS and application actually support IP-based SPNs before you rely on it.
Verify: klist get against the SPN now returns a ticket, and 4769 shows Failure Code: 0x0 for that service.
Problem: KRB_AP_ERR_SKEW or Intermittent Failures (Time Skew)
Symptoms:
- 4771 or 4768 failures with code
0x25on the DC, orKRB_AP_ERR_SKEWin the client’s System log - Failures on some machines only, often VMs restored from snapshot or hosts after a power event
- Also shows up as
KRB_AP_ERR_MODIFIEDin some cases, which is why you check time first
Why it happens: Kerberos rejects tickets when clocks differ by more than the Maximum tolerance for computer clock synchronization. The default is 5 minutes. Members sync from DCs, DCs sync from the PDC emulator, and the PDC emulator should sync from a reliable external source. Break a link in that chain and drift starts. Hypervisor time sync fighting with W32Time is a common culprit.
Fix:
- Check the time source on the affected machine:
w32tm /query /status
Leap Indicator: 0(no warning)
Stratum: 3 (secondary reference – syncd by (S)NTP)
Precision: -23 (119.209ns per tick)
Root Delay: 0.0312500s
Root Dispersion: 7.8233s
ReferenceId: 0x0A000A0A (source IP: 10.0.10.10)
Last Successful Sync Time: 9/25/2026 8:14:02 AM
Source: DC01.contoso.com
Poll Interval: 10 (1024s)
Red flags: Source: Local CMOS Clock, Source: Free-running System Clock, or a Last Successful Sync Time that’s days old.
- Measure the actual offset against the DC:
# /dataonly prints just the offset; 5 samples is enough to spot drift
w32tm /stripchart /computer:DC01.contoso.com /samples:5 /dataonly
- Find the PDC emulator and check that it uses an external source:
netdom query fsmo
w32tm /query /source /computer:DC01.contoso.com
- Fix the member (it should follow the domain hierarchy) and force a resync:
# /syncfromflags:domhier = get time from the domain hierarchy, not a manual peer
w32tm /config /syncfromflags:domhier /update
Restart-Service w32time
w32tm /resync /rediscover
If the PDC emulator itself is wrong, fix its external NTP peers first. Otherwise every DC will faithfully sync to the wrong time. Where internet NTP is blocked, a GPS-disciplined NTP server on the LAN is a solid source for the PDC emulator. Also put DCs on a UPS. A hard power loss is a common reason a DC comes back with a bad clock.
Verify: w32tm /stripchart shows offsets under a second, and the failing client can get a ticket after klist purge.
Problem: Worked Until the 2025 DC or 2026 Update (RC4 / KDC_ERR_ETYPE_NOSUPP)
Symptoms:
- A legacy appliance, NAS, printer, old Java app, or old service account suddenly can’t authenticate
- 4768/4769 failures with
0xE(KDC_ERR_ETYPE_NOSUPP) - Before the break, successful events showed Ticket Encryption Type
0x17(RC4) for that account - Fails only when the client lands on a Windows Server 2025 DC, and works when it hits a 2022 DC
Why it happens: Two changes stack up:
- Windows Server 2025 DCs are AES-first and don’t issue RC4-encrypted TGTs by default. A client that can only do RC4 can’t get a TGT from a 2025 KDC under Microsoft’s standard rollout. Microsoft notes this in What’s new in Windows Server 2025.
- CVE-2026-20833 hardening changed how DCs choose encryption types for service tickets. Accounts with a blank
msDS-SupportedEncryptionTypesget AES-SHA1 by default, and RC4 isn’t implicitly allowed. A blank attribute doesn’t prove the account has AES keys, though (see below). Microsoft’s KB5073381 lays out the phases. Updates from January 13, 2026 added the KDCSVC audit events 201 to 209. The April 14, 2026 update changed the defaultDefaultDomainSupportedEncTypesto AES-SHA1 only (0x18) for accounts without an explicit attribute, with a manual rollback. The July 2026 update started the Enforcement phase and removed theRC4DefaultDisablementPhaserollback setting. Enforcement is the current state on DCs with the July 2026 or later updates. Don’t plan around a temporary audit-mode registry setting. Check the Detect and remediate RC4 page and the Windows message center before relying on any rollback control.
There’s also a quieter third factor. An account may have no AES keys at all. AES keys are created when the password is set on a DC running Windows Server 2008 or later, so an account whose password hasn’t changed since before that may be RC4-only, whatever the attribute says. Creation date or password age is only a clue, not proof. The proof is the key data: on updated DCs, 4768/4769 list the keys available for the account, and the KDCSVC events flag accounts the KDC can’t issue AES tickets for. Microsoft’s Detect and remediate RC4 usage in Kerberos page covers both.
Fix:
- Check what the account supports, and when its password was last set:
Get-ADUser svc_legacyapp -Properties msDS-SupportedEncryptionTypes, KerberosEncryptionType, PasswordLastSet |
Select-Object Name, msDS-SupportedEncryptionTypes, KerberosEncryptionType, PasswordLastSet
Name : svc_legacyapp
msDS-SupportedEncryptionTypes : 4
KerberosEncryptionType : {RC4}
PasswordLastSet : 3/14/2011 9:02:47 AM
A value of 4 means RC4 only. For computers, use Get-ADComputer with the same properties.
- Decode the value:
| Decimal | Hex | Meaning |
|---|---|---|
| (blank) | N/A | Uses the DC’s DefaultDomainSupportedEncTypes default (AES-SHA1 only after the April 2026 phase), which only works if the account actually has AES keys |
| 4 | 0x4 | RC4 only (problem) |
| 24 | 0x18 | AES128 + AES256 (target state) |
| 28 | 0x1C | RC4 + AES128 + AES256 (transitional) |
| 60 | 0x3C | RC4 + AES128 + AES256, plus the AES-SK flag (0x20) that requests AES session keys |
- Find every RC4-dependent account before your users do:
# Prioritization list: accounts explicitly limited to RC4, or with passwords old enough that they might lack AES keys
Get-ADUser -Filter 'ServicePrincipalName -like "*"' -Properties msDS-SupportedEncryptionTypes, PasswordLastSet, ServicePrincipalName |
Where-Object { $_.'msDS-SupportedEncryptionTypes' -eq 4 -or $_.PasswordLastSet -lt (Get-Date '2012-01-01') } |
Select-Object Name, msDS-SupportedEncryptionTypes, PasswordLastSet
Treat the date filter as a heuristic for ordering your work. It can flag accounts that already have AES keys and miss others. Adjust it to when your domain first got Windows Server 2008 or later DCs. Then confirm each account with the 4768/4769 key fields, the KDCSVC events, and 4769 events with TicketEncryptionType = 0x17.
- If the service or device can do AES, switch the account and reset the password so AES keys exist:
Set-ADUser svc_legacyapp -KerberosEncryptionType AES128,AES256
Set-ADAccountPassword svc_legacyapp -Reset -NewPassword (Read-Host -AsSecureString "New password")
Warning: Resetting a service account password breaks every service, scheduled task, app pool, and keytab that uses the old password. Update them all in the same change window. For non-Windows services, regenerate the keytab with AES (for example
ktpass ... -crypto AES256-SHA1) and redeploy it.
- If the device can’t do AES, your options, in order of preference:
- Update or replace it. Check for firmware that adds AES Kerberos. For an old NAS or MFP, that’s often the cheapest fix.
- Use a documented per-account exception. Microsoft’s RC4 remediation guidance covers setting encryption types explicitly on specific accounts. Confirm on the current Learn page that the exception still works in your enforcement phase. Log it as technical debt with an owner and an end date.
- Keep that authentication path on a pre-2025 DC. This only helps with the TGT issue, and only while you still run older DCs. Give it an end date too.
Don’t “fix” this by adding RC4 to DefaultDomainSupportedEncTypes on the DCs. That re-enables RC4 for every account without an explicit setting. You’d undo the protection the CVE-2026-20833 change provides.
Verify: Purge tickets on the client, retry, and confirm 4768/4769 for the account now show an AES type (0x11 AES128 or 0x12 AES256, whichever your policy allows) and Failure Code: 0x0.
Problem: Fix Applied but Still Failing (Stale Tickets)
Symptoms:
- You fixed the SPN, reset the password, or changed encryption types, and nothing changed
- A new user logon works but the existing session doesn’t
- Group membership changes aren’t reflected in share access
Why it happens: Tickets are cached for up to 10 hours by default. The service ticket also carries a snapshot of group membership, so the client keeps presenting the old one. Services running as LocalSystem or NetworkService use the computer account’s ticket cache. A user-level klist purge doesn’t touch it.
Fix:
# Current user's cache
klist purge
# Local System session: computer-account tickets used by services running as SYSTEM (elevated prompt required)
# For a service running under its own account or gMSA, restart that service instead
klist -li 0x3e7 purge
Expected output for each:
Current LogonId is 0:0x5a3c1
Deleting all tickets:
Ticket(s) purged!
For services running under their own accounts, restart the service. Its cache lives in its own logon session. For group changes on the computer account, a reboot is the cleanest option.
Verify: Run klist right after reconnecting. The service ticket should have a fresh Start Time. If you changed encryption types, it should show the new type too.
Problem: Trust Relationship Failed (Broken Secure Channel)
Symptoms:
- “The trust relationship between this workstation and the primary domain failed”
- Computer-account Kerberos fails, affecting GPO processing and
HOST/services - Often follows a VM snapshot revert or a machine that was offline for months
Why it happens: The computer account password on the machine no longer matches the one in AD. The machine can’t decrypt tickets encrypted with its own current key.
Fix:
Test-ComputerSecureChannel -Verbose
VERBOSE: Performing the operation “Test-ComputerSecureChannel” on target “SRV01”.
False
VERBOSE: The secure channel between the local computer and the domain contoso.com is broken.
Repair it with a domain account that has rights to reset the computer password:
Test-ComputerSecureChannel -Repair -Credential (Get-Credential CONTOSO\your-admin-account)
Verify: Test-ComputerSecureChannel returns True, and nltest /sc_verify:contoso.com reports Trusted DC Connection Status Status = 0 0x0 NERR_Success.
What NOT to do: reset krbtgt. Resetting the
krbtgtaccount won’t fix individual failures. Done carelessly, it invalidates every TGT in the domain and can break replication-sensitive environments. If you have a real reason (suspected compromise, key hygiene), follow Microsoft’s documented procedure: two resets, with enough time between them for replication and ticket lifetimes. Schedule it as a planned change. 2 a.m. during an outage is the wrong time to try it.
Problem: It “Works,” but Silently Falls Back to NTLM
Symptoms:
- The app works, but
klistshows no service ticket for its SPN - Security event 4624 on the target shows Authentication Package: NTLM
- Things break the moment you restrict NTLM in a test OU
Why it happens: Negotiate (SPNEGO) tries Kerberos first. When Kerberos fails, it quietly falls back to NTLM. Missing SPNs, IP-based connections, and encryption mismatches all end up here. That fallback hid your Kerberos problems for years, and Microsoft’s published roadmap removes it. NTLMv1 is gone in Windows Server 2025 and Windows 11 24H2, and NTLM overall is deprecated. Microsoft’s January 2026 roadmap runs in three stages. First comes enhanced NTLM auditing, available now in Windows Server 2025 and Windows 11 24H2. Next, new Kerberos features (IAKerb and a local KDC) cover cases that force NTLM today. Last, network NTLM gets disabled by default in a future Windows release. That last stage is a roadmap item, not current Windows Server 2025 behavior: NTLMv2 still works today unless you restrict it. Every silent fallback you find now is a future outage.
Fix:
- Turn on NTLM auditing through GPO (Computer Configuration > Windows Settings > Security Settings > Local Policies > Security Options):
- Network security: Restrict NTLM: Audit Incoming NTLM Traffic → Enable auditing for all accounts (servers)
- Network security: Restrict NTLM: Audit NTLM authentication in this domain → Enable all (DCs only)
- Network security: Restrict NTLM: Outgoing NTLM traffic to remote servers → Audit all (clients)
These settings only audit. They don’t block anything.
- Review Applications and Services Logs > Microsoft > Windows > NTLM > Operational on servers and DCs. The events name the client, the user, and the target. That’s exactly what you need to trace the missing SPN.
- Find NTLM logons on a target server from the Security log:
# NTLM network logons (logon type 3) in the last 24 hours
# Property indexes follow the 4624 event schema; check one event's XML view if results look wrong
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624; StartTime=(Get-Date).AddDays(-1)} |
Where-Object { $_.Properties[10].Value -eq 'NtLmSsp ' -and $_.Properties[8].Value -eq 3 } |
Select-Object TimeCreated, @{n='Account';e={$_.Properties[5].Value}}, @{n='Source';e={$_.Properties[18].Value}} -First 20
- For each hit, work backwards. What name did the client use? Does
setspn -Qfind an SPN for it? Then fix it with the SPN or encryption-type sections above.
Verify: After the fix and a klist purge, the client shows a service ticket for the target in klist, and new 4624 events show Authentication Package: Kerberos.
Error Messages Quick Reference
This is a practical mapping, not a universal event schema. Where a code shows up depends on the stage that fails: the AS exchange (4768/4771), the TGS exchange (4769), or the target service (System log).
| Error | Code | Where you see it | Most likely cause | First command |
|---|---|---|---|---|
KDC_ERR_C_PRINCIPAL_UNKNOWN | 0x6 | 4768 | Account doesn’t exist or wrong domain | Get-ADUser name |
KDC_ERR_S_PRINCIPAL_UNKNOWN | 0x7 | 4769, klist get | Missing SPN; alias or IP used | setspn -Q SPN |
KDC_ERR_ETYPE_NOSUPP | 0xE | 4768 / 4769 | RC4-only account or device | Get-ADUser -Properties msDS-SupportedEncryptionTypes |
KDC_ERR_CLIENT_REVOKED | 0x12 | 4768 / 4771 | Account disabled, locked, or expired | Get-ADUser -Properties LockedOut,Enabled |
KDC_ERR_KEY_EXPIRED | 0x17 | 4768 | Password expired | Get-ADUser -Properties PasswordExpired |
KDC_ERR_PREAUTH_FAILED | 0x18 | 4771 | Wrong or stale password | Check saved credentials on the Client Address |
KRB_AP_ERR_SKEW | 0x25 | 4771 / 4768 on the DC, client System log | Clock off by more than 5 minutes | w32tm /stripchart |
KRB_AP_ERR_MODIFIED | 0x29 | System Event ID 4 | Duplicate or misassigned SPN, stale key, or clock skew | w32tm /stripchart, then setspn -X |
0x80090311 (No authority) | N/A | klist get | No DC reachable | nltest /dsgetdc:domain |
Decision Table: Symptom → Cause → Proof → Fix
| Symptom | Likely cause | Proving command / event | Fix |
|---|---|---|---|
Event ID 4 KRB_AP_ERR_MODIFIED, clocks in sync | Duplicate SPN | setspn -X shows the SPN on 2+ accounts | setspn -D from the wrong account, setspn -S on the right one |
| Event ID 4, no duplicates | SPN on a different account than the service runs as | setspn -Q vs. the service’s StartName | Move the SPN or change the service account |
| Event ID 4 on a Linux/Java service | Stale keytab after password reset | Keytab kvno older than the account’s | Regenerate the keytab with AES |
4769 Failure 0x7 | Missing SPN / alias used | setspn -Q returns “No such SPN found” | Register the SPN or use netdom computername /add |
| Works by name, NTLM by IP | IP-based connection | 4624 with NTLM; no ticket in klist | Use the DNS name |
0x25 or intermittent failures | Time skew | w32tm /stripchart offset over 300s | Fix the hierarchy back to the PDC emulator |
0xE after 2025 DC or 2026 update | RC4-only account or device | 4768/4769 etype fields; attribute = 4 | Set AES, reset the password, regenerate the keytab |
AES set, still 0x17 or 0xE | No AES keys (old password) | PasswordLastSet predates AES support | Reset the password |
| Fix applied, still failing | Stale cached ticket | klist Start Time before the fix | klist purge and klist -li 0x3e7 purge |
| Trust relationship error | Broken secure channel | Test-ComputerSecureChannel = False | Test-ComputerSecureChannel -Repair |
4771 0x18 repeating | Stale saved password | Client Address in 4771 | Update the saved credential or service logon |
Platform-Specific Issues
Mixed Windows Server 2025 and 2019/2022 DCs
The confusing pattern: the same client works in the morning and fails in the afternoon. DC locator hands out different DCs, and only the 2025 DCs refuse RC4 TGTs. Always pin down Kdc Called in klist and the DC from nltest /dsgetdc before you draw conclusions. Check which DCs run which build:
Get-ADDomainController -Filter * | Select-Object Name, OperatingSystem, OperatingSystemVersion, Site
If failures follow the 2025 DCs, you’re almost certainly looking at an RC4 dependency. Skip the SPN hunt.
Linux, Java, and Appliances with Keytabs
Non-Windows services never see a Windows password change. They rely on a keytab. Three rules:
- Generate keytabs with AES (
AES256-SHA1). AvoidRC4-HMAC-NTandAll. - Regenerate the keytab after every password reset on the mapped account.
- The keytab’s key version number (kvno) must match the account’s
msDS-KeyVersionNumber. A mismatch producesKRB_AP_ERR_MODIFIED.
On the Linux side, klist -kte /etc/krb5.keytab lists the encryption types and kvno for each entry.
Homelab Domains
Small labs hit the time issue more than anything else. A single DC VM on a mini PC hypervisor host often syncs from the host’s clock and from W32Time. Pick one: disable hypervisor time sync for the DC, and let the PDC emulator sync to external NTP.
Configuration Issues
Using setspn -A instead of -S. -A adds the SPN without checking for duplicates. That’s how most duplicate SPNs are born. Always use -S.
# Wrong: no duplicate check
setspn -A HTTP/app.contoso.com CONTOSO\svc_app
# Right: refuses if the SPN already exists elsewhere
setspn -S HTTP/app.contoso.com CONTOSO\svc_app
Setting RC4 domain-wide to “fix” one device. DefaultDomainSupportedEncTypes lives at HKLM\SYSTEM\CurrentControlSet\Services\KDC on DCs. It applies to every account without an explicit attribute. Leave it at the AES default, and handle exceptions per account.
Changing the attribute without resetting the password. Setting msDS-SupportedEncryptionTypes to 24 on an account with no AES keys just trades an RC4 failure for an ETYPE_NOSUPP failure. Change the attribute, then reset the password.
Registering the SPN on the computer when the service runs as a user (or the reverse). The SPN goes on the account in the service’s Log On As field, full stop.
Short-name-only SPNs. Register both HTTP/app and HTTP/app.contoso.com if users will type both. They will.
Getting Help
When you escalate to Microsoft support or a community forum, bring this bundle:
klistoutput from the client and fromklist -li 0x3e7. It doesn’t show session keys, but it does expose usernames, the realm, hostnames, and SPNs, so share it through the support case’s secure upload, or redact names before posting to a public forumsetspn -Qfor the target SPN andsetspn -Lfor the service account- Exported 4768/4769/4771 events from the DC that
nltest /dsgetdcreturned, covering the repro time - System log Security-Kerberos events from the client and target
w32tm /query /statusfrom the client, target, and PDC emulator- A packet capture filtered on
KerberosV5, if logs aren’t conclusive (Microsoft’s own guidance recommends this). Captures and diagnostic bundles are far more sensitive thanklistoutput, so send them only through a secure channel
Official references:
- Kerberos authentication troubleshooting guidance
- Detect and remediate RC4 usage in Kerberos
- klist command reference
- What’s new in Windows Server 2025
- Windows release health message center (check here for current RC4 and NTLM enforcement status)
- Microsoft Q&A, tagged windows-server and active-directory
Prevention Checklist
- Run
setspn -X -Fmonthly. Schedule it, and alert on any output other than “found 0 group of duplicate SPNs.” - Use gMSAs for services. Group Managed Service Accounts rotate passwords automatically and support AES out of the box. They also remove the “someone reset the password and forgot the keytab” failure mode. They don’t help non-Windows services, which still need keytabs.
- Make service accounts AES-only. Set
msDS-SupportedEncryptionTypesto 24 explicitly instead of relying on defaults. ConfirmPasswordLastSetis recent enough for AES keys to exist. - Monitor specific events. Alert on 4769 with
TicketEncryptionType = 0x17, 4768/4769 failures0xEand0x7, System Event ID 4 from Security-Kerberos, and the RC4-related KDCSVC events listed on Microsoft’s remediation page. - Keep NTLM auditing on permanently. Review the NTLM Operational log each quarter, and treat every new NTLM source as a bug.
- Protect the time chain. Configure the PDC emulator with external NTP peers, move that config when you transfer the role, and alert when a DC reports
Local CMOS Clock. - Track Microsoft’s enforcement dates. Subscribe to the release health message center so the next hardening phase doesn’t surprise you.
- Keep krbtgt resets planned. Run them only through the documented two-reset procedure, in a change window.
Frequently Asked Questions
Why did Kerberos stop working after adding a Windows Server 2025 DC?
Most often, something in your environment was RC4-only. Windows Server 2025 DCs don’t issue RC4 TGTs.
The 2026 CVE-2026-20833 enforcement also stopped implicitly allowing RC4 for accounts without explicit encryption types. Check 4768/4769 on the 2025 DC for 0xE failures or earlier 0x17 tickets.
What does KRB_AP_ERR_MODIFIED actually mean?
The target service received a ticket it couldn’t decrypt. The ticket was encrypted with some account’s key, but not the key the service holds.
The usual causes are a duplicate SPN, an SPN on the wrong account, or a stale keytab or password. Less often, it’s clock skew.
How do I tell SPN vs. encryption vs. time problems apart without changing anything?
Look at the failure code. 0x7 points to a missing SPN. Event ID 4 usually means a duplicate or misassigned SPN or a stale key once you’ve ruled out clock skew.
Prove either with setspn -Q and -X. 0xE points to encryption, so check msDS-SupportedEncryptionTypes and PasswordLastSet.
0x25 points to time, so prove it with w32tm /stripchart. All three checks take under five minutes, and none of them change config.
Is it safe to run klist purge on a production server?
Yes. klist purge only drops cached tickets, and the next request fetches fresh ones. klist -li 0x3e7 purge affects services running as SYSTEM, which briefly re-authenticate. In most cases it won’t log anyone out or break active sessions.
Should I reset krbtgt to fix ticket problems?
No. It won’t fix SPN, time, or encryption-type failures, and a careless reset can cause domain-wide authentication problems. Use Microsoft’s documented two-reset procedure only for a planned, justified rotation.
Wrapping Up
The pattern that works every time: read the failure code, run the one command that proves it, make the smallest change, and purge tickets. 0x7 sends you to setspn -Q. 0xE sends you to the account’s encryption types and password age, and 0x25 sends you to w32tm.
Most “Kerberos is broken” tickets in 2026 are old RC4 debt and NTLM fallback coming due at once. Hunting down the 0x17 tickets and NTLM logons now costs far less than finding them during an outage.
| Step | Action | Applies To |
|---|---|---|
| 1 | nltest /dsgetdc, purge caches, reproduce | Every failure |
| 2 | klist get SPN and read the error | Every failure |
| 3 | Check 4768/4769/4771 on the right DC | KDC-side failures |
| 4 | setspn -Q, setspn -X | 0x7, Event ID 4 |
| 5 | w32tm /query /status, /stripchart | 0x25, intermittent |
| 6 | Check msDS-SupportedEncryptionTypes + PasswordLastSet | 0xE, RC4 after 2025/2026 changes |
| 7 | klist purge + klist -li 0x3e7 purge | After any fix |
| 8 | Audit NTLM Operational log and 4624 | “Works” but no Kerberos ticket |
Last updated: September 25, 2026 | Applies to Kerberos authentication on Windows Server 2025 Active Directory domains, including mixed 2019/2022 DC environments