I have added, as per user requirements, a custom field to the Quote Product entity (quotedetail) of CRM, allowing integration with our financial system (which is not currently in the scope of this problem). The field is named Summary Text Code, and is a lookup to a custom record type that exists purely for this purpose. In our development instance of CRM, this works perfectly, but in the Staging/UAT environment, all users (from the most limited up to SysAdmins) get the following error when attempting to save a record with a value set in this field:
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: An unexpected error occurred.Detail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ErrorCode>-2147220970</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
<KeyValuePairOfstringanyType>
<d2p1:key>CallStack</d2p1:key>
<d2p1:value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:string"> at Microsoft.Crm.Extensibility.VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.Pipeline.Execute(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.MessageProcessor.Execute(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.InternalMessageDispatcher.Execute(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.ExternalMessageDispatcher.ExecuteInternal(IInProcessOrganizationServiceFactory serviceFactory, IPlatformMessageDispatcherFactory dispatcherFactory, String messageName, String requestName, Int32 primaryObjectTypeCode, Int32 secondaryObjectTypeCode, ParameterCollection fields, CorrelationToken correlationToken, CallerOriginToken originToken, UserAuth userAuth, Guid callerId, Guid transactionContextId, Int32 invocationSource, Nullable`1 requestId, Version endpointVersion)
at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, UserAuth userAuth, Guid targetUserId, Boolean traceRequest, OrganizationContext context, Boolean returnResponse)
at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType)
at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.Execute(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType)</d2p1:value>
</KeyValuePairOfstringanyType>
</ErrorDetails>
<Message>An unexpected error occurred.</Message>
<Timestamp>2014-07-23T21:56:55.0044932Z</Timestamp>
<InnerFault i:nil="true" />
<TraceText i:nil="true" />
</OrganizationServiceFault>
A little Google-fu turned up the implication that this was a plugin problem. However, we have text file logging of our plugins, especially the one we have for Quote Products, and the plugin is not even entered in this situation.
What's even weirder is that the error does not occur when the value of this field is not set, so it's really hard for me to assert that I'm not at fault.
A little deeper digging into the event viewer and WER logs returns the following, more detailed error with a stack trace crossing the web service boundary:
Exception generated at: 7/23/2014 5:13:54 PM
Error Type: System.InvalidCastException
Error Message: Specified cast is not valid.
Error Stack Trace:
at SecurityAttributes..ctor(SecurityTraits traits, Guid objectId, Boolean allowNonUniqueRows, ArrayList attributes, ExecutionContext context) ilOffset = 0xB1
at SecurityAttributes..ctor(SecurityTraits traits, Guid objectId, ArrayList attributes, ExecutionContext context) ilOffset = 0x7
at SecurityExtension.GetSecurityAttributes(BusinessEntity entity, AttributeMetadata attribute, ExtensionEventArgs e, Relationship& relationship, SecurityTraits& traits) ilOffset = 0x5E
at SecurityExtension.CheckAppendAccess(BusinessEntity entity, ExtensionEventArgs e) ilOffset = 0x29
at SecurityExtension.PreUpdateHandlerAppendAppendToPrivilegeCheck(Object sender, SecurityTraits traits, SecurityAttributes attributes, ExtensionEventArgs e) ilOffset = 0x28
at SecurityExtension.PreUpdateHandler(ExtensionEventArgs e, Object sender) ilOffset = 0x39
at PreUpdateEventHandler.Invoke(Object sender, ExtensionEventArgs e) ilOffset = 0xFFFFFFFF
at BusinessProcessObject.UpdateWithPipelineAndExtensions(IBusinessEntity entity, ExecutionContext context) ilOffset = 0x6F
at QOIDetailService.Update(IBusinessEntity qoiDetail, ExecutionContext context, Boolean calculatePrice, Boolean checkState, BusinessEntity parentQoi) ilOffset = 0x5B
at QuoteDetailService.Update(IBusinessEntity quoteDetail, ExecutionContext context) ilOffset = 0x78
Stack Frame:
at Pipeline.Execute(PipelineExecutionContext context) ilOffset = 0x65
at MessageProcessor.Execute(PipelineExecutionContext context) ilOffset = 0x1C5
at InternalMessageDispatcher.Execute(PipelineExecutionContext context) ilOffset = 0xE4
at ExternalMessageDispatcher.ExecuteInternal(IInProcessOrganizationServiceFactory serviceFactory, IPlatformMessageDispatcherFactory dispatcherFactory, String messageName, String requestName, Int32 primaryObjectTypeCode, Int32 secondaryObjectTypeCode, ParameterCollection fields, CorrelationToken correlationToken, CallerOriginToken originToken, UserAuth userAuth, Guid callerId, Guid transactionContextId, Int32 invocationSource, Nullable`1 requestId, Version endpointVersion) ilOffset = 0x156
at OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType, UserAuth userAuth, Guid targetUserId, Boolean traceRequest, OrganizationContext context, Boolean returnResponse) ilOffset = 0x145
at OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType) ilOffset = 0x3D
at OrganizationSdkServiceInternal.Execute(OrganizationRequest request, CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType) ilOffset = 0x24
at InprocessServiceProxy.ExecuteCore(OrganizationRequest request) ilOffset = 0x34
at PlatformCommand.XrmExecuteInternal() ilOffset = 0xF6
at UpdateCommand.Execute() ilOffset = 0x7
at DataSource.Update(EntityProxy entity, Boolean performDuplicateCheck, Guid auditingTransactionId, IOrganizationContext context) ilOffset = 0x11
at EntityProxy.Update(Boolean performDuplicateCheck, Guid auditingTransactionId) ilOffset = 0x0
at EntityProxy.Update(Boolean performDuplicateCheck) ilOffset = 0x7
at AppForm.SaveEntity(EntityProxy entity, FormEventId eventType, String redirectPath, Boolean performDuplicateCheck) ilOffset = 0x2A
at AppForm.Save(Boolean& gridRefreshCallbackAdded) ilOffset = 0x47
at AppForm.FormSaveEvent() ilOffset = 0xD
at AppForm.RaiseDataEvent(FormEventId eventId) ilOffset = 0xCF
at EndUserForm.Initialize(Entity entity) ilOffset = 0x1F
at CustomizableForm.Execute(Entity entity, FormDescriptor fd) ilOffset = 0x62
at QuoteDetailRecordPageHandler.ConfigureFormHandler() ilOffset = 0x98
at RecordPageHandler.ConfigureFormWrapper() ilOffset = 0xC
at GenericEventProcessor.RaiseEvent(String eventName) ilOffset = 0x2D
at PageManager.OnPreRender(EventArgs e) ilOffset = 0x47
at Control.PreRenderRecursiveInternal() ilOffset = 0x54
at Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) ilOffset = 0x6D3
at Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) ilOffset = 0x3C
at Page.ProcessRequest() ilOffset = 0x14
at Page.ProcessRequest(HttpContext context) ilOffset = 0x33
at CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() ilOffset = 0x18D
at HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) ilOffset = 0x15
at ApplicationStepManager.ResumeSteps(Exception error) ilOffset = 0x10A
at HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) ilOffset = 0x5C
at HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) ilOffset = 0x16A
at ISAPIRuntime.ProcessRequest(IntPtr ecb, Int32 iWRType) ilOffset = 0x4B
Exception Data:
1: Key type: System.String, value: PluginTrace
Custom Message: Web Service Plug-in failed in SdkMessageProcessingStepId: a8cdbb1b-ea3e-db11-86a7-000a3a5473e8; EntityName: quotedetail; Stage: 30; MessageName: Update; AssemblyName: Microsoft.Crm.Extensibility.InternalOperationPlugin, Microsoft.Crm.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35; ClassName: Microsoft.Crm.Extensibility.InternalOperationPlugin; Exception: Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Web.Services.Protocols.LogicalMethodInfo.Invoke(Object target, Object[] values)
at Microsoft.Crm.Extensibility.InternalOperationPlugin.Execute(IServiceProvider serviceProvider)
at Microsoft.Crm.Extensibility.V5PluginProxyStep.ExecuteInternal(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)
Inner Exception: System.InvalidCastException: Specified cast is not valid.
at Microsoft.Crm.BusinessEntities.SecurityAttributes..ctor(SecurityTraits traits, Guid objectId, Boolean allowNonUniqueRows, ArrayList attributes, ExecutionContext context)
at Microsoft.Crm.BusinessEntities.SecurityAttributes..ctor(SecurityTraits traits, Guid objectId, ArrayList attributes, ExecutionContext context)
at Microsoft.Crm.BusinessEntities.SecurityExtension.GetSecurityAttributes(BusinessEntity entity, AttributeMetadata attribute, ExtensionEventArgs e, Relationship& relationship, SecurityTraits& traits)
at Microsoft.Crm.BusinessEntities.SecurityExtension.CheckAppendAccess(BusinessEntity entity, ExtensionEventArgs e)
at Microsoft.Crm.BusinessEntities.SecurityExtension.PreUpdateHandlerAppendAppendToPrivilegeCheck(Object sender, SecurityTraits traits, SecurityAttributes attributes, ExtensionEventArgs e)
at Microsoft.Crm.BusinessEntities.SecurityExtension.PreUpdateHandler(ExtensionEventArgs e, Object sender)
at Microsoft.Crm.BusinessEntities.BusinessProcessObject.PreUpdateEventHandler.Invoke(Object sender, ExtensionEventArgs e)
at Microsoft.Crm.BusinessEntities.BusinessProcessObject.UpdateWithPipelineAndExtensions(IBusinessEntity entity, ExecutionContext context)
at Microsoft.Crm.ObjectModel.QOIDetailService.Update(IBusinessEntity qoiDetail, ExecutionContext context, Boolean calculatePrice, Boolean checkState, BusinessEntity parentQoi)
at Microsoft.Crm.ObjectModel.QuoteDetailService.Update(IBusinessEntity quoteDetail, ExecutionContext context)
At this point I'm stumped. Not a single line of any error trace even goes through custom code, much less terminating at one, so this appears to be 100% CRM throwing a fit for reasons I cannot yet understand.