0X80090317

SEC_E_CONTEXT_EXPIRED (0x80090317): What Actually Breaks

0x80090317 means your app held an authentication context past its lifetime. Here's how to fix it fast, and why it happens in the first place.

SEC_E_CONTEXT_EXPIRED (0x80090317) shows up when a client tries to keep using a security context after the underlying ticket (Kerberos, NTLM, or Schannel) has already been torn down. The context handle is still valid in memory. The credentials behind it aren't. Windows returns the error the moment the next call tries to read that dead context.

What's actually happening here is that SSPI contexts have a lifetime. Kerberos tickets default to 10 hours. Schannel session tickets live ~10 hours on Windows Server 2019/2022 unless the app refreshes them. If your code caches the CtxtHandle or the SslStream and reuses it hours later, you'll get 0x80090317 instead of a silent reconnect.

Cause 1: The app caches a context past its lifetime

This is the number one trigger. Long-running services — Windows services, IIS app pools, .NET background workers, Java daemons running for weeks — establish an authenticated connection at startup and never re-auth. Around the 10-hour mark the ticket expires, and the next operation returns SEC_E_CONTEXT_EXPIRED.

Real scenario: a Windows service polls a WinRM endpoint every 60 seconds. It runs fine overnight, then at 07:15 the operations team sees a burst of 0x80090317 in the event log. The service started at 21:00 the previous day. That's the 10-hour Kerberos default hitting it.

The real fix is to treat the context as disposable. Don't keep a single SSPI handshake alive across the entire process lifetime.

// Wrong: cached context reused forever
if (!_ctx.IsValid) {
    _ctx = NegotiateAuth(target);
}
CallApi(_ctx);

// Right: re-auth on SEC_E_CONTEXT_EXPIRED
var hr = CallApi(_ctx);
if (hr == unchecked((int)0x80090317)) {
    _ctx.Dispose();
    _ctx = NegotiateAuth(target);
    hr = CallApi(_ctx);
}

If you can't refactor the client, shorten the token lifetime so the failure surfaces during business hours and gets handled, or bump the ticket lifetime. On the domain controller, Kerberos policy controls this:

Group Policy > Computer Configuration > Windows Settings >
Security Settings > Account Policies > Kerberos Policy
  Maximum lifetime for user ticket:  10 hours (default)
  Maximum lifetime for service ticket: 600 minutes (default)
  Maximum lifetime for user ticket renewal: 7 days (default)

Renewal is set to 7 days by default, so an app that calls InitializeSecurityContext with the renew flag can extend an existing ticket without a full re-auth. Most code doesn't do that. Fix the code instead of trying to make tickets live forever.

Cause 2: Clock skew invalidates the ticket on the server side

Kerberos rejects tickets when the client and KDC clocks drift more than 5 minutes. The client thinks the context is fine. The server sees a ticket with a start time in the future or an expiry in the past and drops the context. The client then gets 0x80090317 on the next call.

This one shows up after VM snapshots, restored domain controllers, or hosts booting from stale RTC after a power event. I've seen it on AWS EC2 Windows AMIs where the hypervisor clock resync was disabled and the guest drifted 7 minutes over three weeks.

Check it:

w32tm /stripchart /computer:dc01.contoso.com /samples:5 /dataonly
w32tm /query /status
w32tm /resync /force

On domain members, the w32time service should already be syncing to the domain hierarchy. If it isn't, sysadmin probably disabled it thinking the hypervisor handled it. Re-enable:

sc config w32time start= auto
net start w32time
w32tm /config /syncfromflags:domhier /update
w32tm /resync /rediscover

Don't fix time by manually typing a date. That breaks the clock sequence number Kerberos tracks. Use w32tm, or if it refuses, reboot the VM and let it pull from the KDC at startup.

Cause 3: A stale service ticket on the application server

The client authenticates fine, but the server-side app has a cached service ticket that expired. Common with SQL Server linked servers, Exchange MAPI/RPC services, and SharePoint claims providers. The client call looks correct, yet the server returns SEC_E_CONTEXT_EXPIRED in the SSPI layer.

SQL Server is the classic case. A linked server configured with Be made using the login's current security context holds a delegated Kerberos context per login. After ~10 hours the ticket dies and every query against the linked server throws:

Msg 7399, Level 16, State 1, Line 1
The OLE DB provider "SQLNCLI11" for linked server "Sales01" reported an error.
Cannot initialize the data source object of OLE DB provider...
OLE DB error trace [OLE/DB Provider 'SQLNCLI11' ...]
Error 0x80090317: SEC_E_CONTEXT_EXPIRED.

Two paths. First, refresh the linked server mapping by re-running sp_addlinkedsrvlogin or restarting SQL Agent, which is a band-aid. The real fix is to check the SPNs. Missing or duplicate SPNs cause Kerberos to fall back to NTLM, and NTLM contexts have much shorter lifetimes. Verify with:

setspn -L SQLServiceAccount
setspn -Q MSSQLSvc/sql01.contoso.com:1433

You should see exactly one SPN per instance per FQDN, owned by the SQL service account. Duplicates on the machine account are the classic failure — they cause KRB_AP_ERR_MODIFIED or a silent downgrade to NTLM, which then expires on you.

For Exchange or IIS hostnames, same story. The app pool identity needs a valid SPN or Kerberos can't negotiate, and the fallback path burns you with 0x80090317 hours later.

What doesn't fix it

  • Restarting the client machine. The context rebuilds and then dies again at the same interval. You've hidden the symptom, not the cause.
  • Disabling Kerberos and forcing NTLM. NTLM contexts expire faster, so you've made the problem worse.
  • Tweaking MaxTokenSize. That's for 0x8009030C, a different error entirely.
  • Adding the SPN "just to be sure" without checking for duplicates. Duplicates are usually the actual problem.

Quick reference

SymptomLikely causeFirst thing to check
Fails after ~10 hours of uptimeCached SSPI context past ticket lifetimeRefresh context on 0x80090317, or call InitializeSecurityContext with renew flag
Intermittent, matches clock drift eventsClient/KDC clock skew > 5 minw32tm /stripchart against the PDC emulator
SQL linked server, Exchange, SharePointStale service ticket or bad/missing SPNsetspn -Q, look for duplicates
Started right after VM restore or snapshotGuest clock behind KDCw32tm /resync /rediscover, then reboot
Only on one server, others fineServer-side app pool or service accountRecycle the app pool; verify the service account's SPN

If none of the above sticks, enable SSPI logging. On Windows Server 2019/2022, set HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\LogLevel to 1 and check the System event log. The Kerberos-Key-Distribution-Center events will tell you whether the KDC rejected the ticket and why, which beats guessing every time.

Related Errors in Cybersecurity & Malware
0x80070422 Windows Update Disabled by Unknown Policy – Fix in 3 Steps MBAM-SVC-5003 Malwarebytes Won't Open? Fix the 'Service Not Available' Error Fix Windows Security 'Virus & threat protection' won't turn on 0XC00D280D Fix NS_E_DRM_LICENSE_NOTRUSTEDCODEC 0xC00D280D in Windows Media Player

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.