CRM 2013 – Workflow error AccessCheckEx

I was investigating a bug on CRM 2013 , I got the exception below

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: f115e97d-8e19-e511-80ca-000c292122be, OwnerId: 89ed0bdd-7ecd-e411-80c7-000c292122be,  OwnerIdType: 9 and CallingUser: 2ed69167-0bcf-e411-80c7-000c292122be. ObjectTypeCode: 4200, objectBusinessUnitId: 5f964320-05f4-e411-80c9-000c292122be, AccessRights: WriteAccess Detail:
<OrganizationServiceFault xmlns:i=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns=”http://schemas.microsoft.com/xrm/2011/Contracts”&gt;
  <ErrorCode>-2147220891</ErrorCode>
  <ErrorDetails xmlns:d2p1=”http://schemas.datacontract.org/2004/07/System.Collections.Generic”&gt;
    <KeyValuePairOfstringanyType>
      <d2p1:key>OperationStatus</d2p1:key>
      <d2p1:value xmlns:d4p1=”http://www.w3.org/2001/XMLSchema&#8221; i:type=”d4p1:string”>0</d2p1:value>
    </KeyValuePairOfstringanyType>
    <KeyValuePairOfstringanyType>
      <d2p1:key>SubErrorCode</d2p1:key>
      <d2p1:value xmlns:d4p1=”http://www.w3.org/2001/XMLSchema&#8221; i:type=”d4p1:string”>-2146233088</d2p1:value>
    </KeyValuePairOfstringanyType>
  </ErrorDetails>
  <Message>SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: f115e97d-8e19-e511-80ca-000c292122be, OwnerId: 89ed0bdd-7ecd-e411-80c7-000c292122be,  OwnerIdType: 9 and CallingUser: 2ed69167-0bcf-e411-80c7-000c292122be. ObjectTypeCode: 4200, objectBusinessUnitId: 5f964320-05f4-e411-80c9-000c292122be, AccessRights: WriteAccess </Message>
  <Timestamp>2015-06-23T10:02:24.458209Z</Timestamp>
  <InnerFault i:nil=”true” />
  <TraceText>

[Microsoft.Crm.ObjectModel: Microsoft.Crm.ObjectModel.SyncWorkflowExecutionPlugin]
[0dac4467-fb18-e511-80ca-000c292122be: ]
Starting sync workflow ‘Task-Workflow’, Id: 04ac4467-fb18-e511-80ca-000c292122be
Entering ConditionStep1_step: If  Process contains data and is active
Entering SetStateStep4_step: Change record status to completed
Sync workflow ‘Task-Complete’ terminated with error ‘SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: f115e97d-8e19-e511-80ca-000c292122be, OwnerId: 89ed0bdd-7ecd-e411-80c7-000c292122be,  OwnerIdType: 9 and CallingUser: 2ed69167-0bcf-e411-80c7-000c292122be. ObjectTypeCode: 4200, objectBusinessUnitId: 5f964320-05f4-e411-80c9-000c292122be, AccessRights: WriteAccess ‘
</TraceText>
</OrganizationServiceFault>

Initial thoughts on the Error

I got this error and there were a few things I found interesting

This error was surprisingly informative

The error was thrown by a non code workflow but the cause of the error was thrown by a GUI workflow which was being triggered when a workflow tried to assign an activity.

I was impressed by the level of logging which was generated by a GUI/non code workflow.

I had never thought about it but this line

Microsoft.Crm.ObjectModel: Microsoft.Crm.ObjectModel.SyncWorkflowExecutionPlugin

indicates CRM runs the GUI workflows using code, which must translate the actions into code. This is obvious but I hadn’t thought about it, until seeing the error.

You can use the callerid to find what user is doing the update and check what security roles the user has.

EntityTypeCode

In the error message you can see it mentions ObjectTypeCode

CRM 2011/2013 – Javascript to get the object type code of an entity

Each entity has an individual typecode, this CRM SDK page shows you the values of the default entities

Entity Type Code 4200 is ActivityPointer, which is interesting because the problem was being caused by an update to a task record.

Clues

AccessCheckEx failed – AccessCheckEx is something to do with security and access

In the error message you can see

AccessRights: WriteAccess

This is clearly telling us the user doesn’t have Write access, e.g. the user isn’t allow to update a certain

What was the cause

This bug was partly caused by the complexity of the CRM solution and the different customizations.

Solution complexity refer to not only the customizations which exist in the solution but the number of different customizations.  When a CRM solution has lots of different customizations e.g. workflows, plugins, business rules being triggered at the same time it makes it difficult to understand what is changing a value.

Below is what was happening

  1. A task was updated then saved
  2. This triggered a pre plugin on the task entity
  3. The plugin assigns the case record
  4. A plugin was triggered on assign of the case, which assigned all the open tasks to the new case owner
  5. The plugin(s) finished
  6. A workflow was triggered, which tried set the task to complete.

The error was thrown because the workflow was trying to update the task but the user only had privileges to update tasks they owned.

The reason this bug suddenly appeared was because the assign plugin was added and it wasn’t picked up in DEV testing because developers tested the code using users with System Admin privileges, which I have talked about before

The System Administrator role is a benefit and a curse to CRM developers

It’s tricky to test the effect of adding plugins

Having lots of different types of customizations adds to the complexity of your CRM solution, complex solutions are difficult to debug, understand and extend.

The Solution

Usually with bugs where the user doesn’t have the right security privilege the easy answer is to give the user role those security privileges.

For this bug it wasn’t the correct solution because the users only had access to tasks they owned and we didn’t want to suddenly give them permissions to update tasks they didn’t own.

The plugin code was running in a PRE plugin, so I couldn’t move the task completing code into this plugin.

The bug was becoming more tricky because I did want to keep the case assigning code in their but I didn’t want the assigning case plugin to run and assign the task to the new case owner because the task was about to completed.

My solution was to stop the assign plugin being triggered if was called by another plugin

Read how to do that in the blog below

CRM Plugins – Stopping infinite loops and understanding PluginExecutionContext.Depth

I then created a post task plugin to complete the task.  I didn’t need to do this but it seemed it would be easy to understand if all the changes were made by plugins.

There was an unsuccessful fix when I used impersonation to close the task as System Admin but the users didn’t like the tasks being closed by System Admin, they wanted the user who updated the task to complete the task.

You can read about Impersonation in plugins in the blog post below

CRM 2015 – Understanding impersonation in plugins and knowing when to use it

CRM 2011 – Why error logs are great in Excel

I have been banging my head against my keyboard today.

Having been tasked with updating the solutions and customizations on one of the servers which had beenn set to Production but was now 3 months out of date.

This meant I had to deploy 30 solutions and update all sorts of dll’s and static data.

 

ERROR ALERT

I got this head banging error on the 3rd solution import of the day!

We split our solutions in different parts – Entities, Processes (workflows), Plugins and security roles.

The error occurred on the plugin import and the error in the import log was frustratingly stupid and annoying (the best errors are)

import error

The message says

An error has occurred contact your CRM Administrator or Microsoft Dyanmics community or as a last resort Microsoft Support.

The special trick is if you open the file using internet explorer, you just get an xml list of all the components and no real error message.   The reason it opens in IE is because I was on the server and it didn’t have excel installed!

This is the import error file in IE

import error 1

 

It goes on and on and it’s pretty much useless.

So I had to copy and paste it over a bunch of servers until I could finally get it to a machine which had excel and then hey presto, you get two tabs, solutions (hold general info) and components (detailed info – yippeee).  Here is the file and I have Hoskified the real content

import error 2

I open the component sheet and finally I get an actual error message

14:54:45.30 Plugin Assembly Plugins.Common Plugins.Common Plugins.Common Failure 0x8004418B Plug-in assembly does not contain the required types or assembly content cannot be updated.

Which says this

Plug-in assembly does not contain the required types or assembly content cannot be updated.

 

No I don’t really know what the heck that means but we had gone from one major release 1 to release 2.  For these two major releases we created two different solutions.  This mean when I came to importing the plugins, it didn’t bring up the choice of overwriting or maintaining.

I think what was happening it was was trying to update a plugin but was having trouble because it was trying to do it from a different solution but I don’t think this should really be the reason because it’s the same publisher.

 

To resolve the problem I opened up the good old faithful Plugin Registration tool, in it’s beautiful old fashioned look (none of this CRM 2013 fancy pants plugin registration tool in CRM 2011).

I took the bold decision to unregistered the offending plugin.  I had backup my database but I also thought the new solution had a new copy of the plugin, so it should be a problem.

 

 WHAT HAPPENED…..

I imported the solution again and got another error, a different plugin was clinging onto dear life and not allowing himself to be deleted (the matrix nonsense about code is true!).

I unregistered that plugin, wondered how many plugins I would have to unregister to get this solution to successfully imported.

Next import the plugin solution installed, HAZAAR, Hosk 1 – CRM 0

 

I then had to import another 27 solutions, yawn…but thankfully without incident

Another exciting day in the Life of the Hosk,  it reminds me of the saying