Wednesday, February 5, 2014

SharePoint issue “The context has expired and can no longer be used. Exception from HRESULT 0x80090317”

Problem
A client had problems with some workflow instances. Most instances did complete without a problem others failed.  Especially workflow that continued after a few days reported the following error in the workflow history log:
“{Microsoft.SharePoint.SPException: The context has expired and can no longer be used. (Exception from HRESULT: 0x80090317) ---> System.Runtime.InteropServices.COMException (0x80090317): The context has expired and can no longer be used. (Exception from HRESULT: 0x80090317)
   at Microsoft.SharePoint.Library.SPRequestInternalClass.SetHttpParameters(String bstrHttpMethod, String “

I did some googling and found some hits that found a solution in synchronizing the date/time of the WFE’s and admin servers. In our case that wasn’t the the case.

Cause
After digging into the problem I noticed particular workflow activity opened a site collection using an SPUserToken.
using (SPSite site = new SPSite(WorkflowProperties.SiteId, InitializationData.UserToken))
{
//do some work
}
The SPUserToken was part of the workflow context and was populated when the workflow instance was first created. Default the SPUserToken is valid for 1440 minutes (1 day). In case the workflow instance is de-hydrated after more than 1 day the SPUserToken is expired and isn’t valid anymore. You will get the message “The context has expired and can no longer be used. (Exception from HRESULT: 0x80090317” and are not allowed to open the sitecollection.

Conclusion
So when you get this specific error make sure to check if you use an old SPUserToken! And be aware the the SPUserToken can expire.

Detailed exception information
Full error message: "The context has expired and can no longer be used. (Exception from HRESULT: 0x80090317)"
Sample Stacktrace:
{Microsoft.SharePoint.SPException: The context has expired and can no longer be used. (Exception from HRESULT: 0x80090317) ---> System.Runtime.InteropServices.COMException (0x80090317): The context has expired and can no longer be used. (Exception from HRESULT: 0x80090317)
   at Microsoft.SharePoint.Library.SPRequestInternalClass.SetHttpParameters(String bstrHttpMethod, String bstrRequestDigest, UInt32 flags, Guid gTranLockerId, Byte[]& ppsaImpersonateUserToken, Boolean bIgnoreTimeout, String bstrUserLogin, String bstrUserKey, UInt32 ulRoleCount, String bstrRoles, Boolean bWindowsMode, ApplicationPrincipalInfo& pAppUserInfo, Boolean bInvalidateCachedConfigurationProperties, Int32 lAppDomainId, ISPManagedObjectFactory pFactory, Boolean bCallstack)
   at Microsoft.SharePoint.Library.SPRequest.SetHttpParameters(String bstrHttpMethod, String bstrRequestDigest, UInt32 flags, Guid gTranLockerId, Byte[]& ppsaImpersonateUserToken, Boolean bIgnoreTimeout, String bstrUserLogin, String bstrUserKey, UInt32 ulRoleCount, String bstrRoles, Boolean bWindowsMode, ApplicationPrincipalInfo& pAppUserInfo, Boolean bInvalidateCachedConfigurationProperties, Int32 lAppDomainId, ISPManagedObjectFactory pFactory, Boolean bCallstack)
   --- End of inner exception stack trace ---
   at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)
   at Microsoft.SharePoint.Library.SPRequest.SetHttpParameters(String bstrHttpMethod, String bstrRequestDigest, UInt32 flags, Guid gTranLockerId, Byte[]& ppsaImpersonateUserToken, Boolean bIgnoreTimeout, String bstrUserLogin, String bstrUserKey, UInt32 ulRoleCount, String bstrRoles, Boolean bWindowsMode, ApplicationPrincipalInfo& pAppUserInfo, Boolean bInvalidateCachedConfigurationProperties, Int32 lAppDomainId, ISPManagedObjectFactory pFactory, Boolean bCallstack)
   at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(SPSite site, String name, Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous)
   at Microsoft.SharePoint.SPWeb.InitializeSPRequest()
   at Microsoft.SharePoint.SPWeb.InitWebPublic()
   at Microsoft.SharePoint.SPWeb.get_CurrentUser()