Troubleshoot plug-ins

This topic contains information about errors that can occur due to plug-ins and how to fix them.

Transaction errors

There are two common types of errors related to transactions:

Error Code: -2146893812
Error Message: ISV code reduced the open transaction count. Custom plug-ins should not catch exceptions from OrganizationService calls and continue processing.

Error Code: -2147220911
Error Message: There is no active transaction. This error is usually caused by custom plug-ins that ignore errors from service calls and continue processing.

Note

The top error was added most recently. It should occur immediately and in the context of the plug-in that contains the problem. The bottom error can still occur in different circumstances, typically involving custom workflow activities. It may be due to problems in another plug-in.

To understand the message, you need to appreciate that any time an error related to a data operation occurs within a synchronous plug-in the transaction for the entire operation will be ended.

More information: Scalable Customization Design in Common Data Service

The most common cause is simply that a developer might believe they can attempt to perform an operation that might succeed so they wrap that operation in a try/catch block and attempt to swallow the error if it fails.

While this may work for a client application, within the execution of a plug-in any data operation failure will result in rolling back the entire transaction. You can't swallow the error, so you must make sure to always return an InvalidPluginExecutionException.

Error: Sql error: Execution Timeout Expired

Error Code: -2147204783
Error Message: Sql error: 'Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.'

There are a wide variety of reasons that a SQL timeout error may occur.

Blocking

Blocking is the most common cause for a SQL Timeout error is that the operation is waiting for resources that are being locked by another SQL transaction. The error is the result of the system protecting the integrity of the data and from long running requests that impact performance for users.

Blocking may be due to other concurrent operations. Your code may work fine in isolation in a test environment and still be susceptible to conditions that will only occur when multiple users are initiating the logic in your plug-in.

When writing plug-ins, it is essential to understand how to design customizations that are scalable. More information: Scalable Customization Design in Common Data Service

Cascade operations

Certain actions you make in your plug-in, such as assigning or deleting a record, can initiate cascading operations on related records. These actions could apply locks on related records causing subsequent data operations to be blocked which in turn can lead to a SQL timeout.

You should consider the possible impact of these cascading operations on data operations in your plug-in. More information: Entity relationship behavior

Because these behaviors can be configured differently between environments, the behavior may be difficult to reproduce unless the environments are configured in the same way.

Indexes on new entities

If the plug-in is performing operations using an entity or attribute that has been created recently, some Azure SQL capabilities to manage indexes might make a difference after a few days.

Errors due to user privileges

In a client application you can disable commands that users are not allowed to perform. Within a plug-in you don't have this. Your code may include some automation that the calling user doesn't have the privileges to perform.

You can register the plug-in to run in the context of a user known to have the correct privileges by setting the Run in User's Context value to that user. Or you can execute the operation impersonating another user. More information:

Error: Message size exceeded when sending context to Sandbox

Error Code: -2147220970
Error Message: Message size exceeded when sending context to Sandbox. Message size: ### Mb

This error occurs when a message payload is greater than 116.85 MB AND a plug-in is registered for the message. The error message will include the size of the payload that caused this error.

The limit will help ensure that users running applications cannot interfere with each other based on resource constraints. The limit will help provide a level of protection from unusually large message payloads that threaten the availability and performance characteristics of the Common Data Service platform.

116.85 MB is large enough that it should be rare to encounter this case. The most likely situation where this case might occur is when you retrieve a record with multiple related records which include large binary files.

If you encounter this error you can:

  1. Remove the plug-in for the message. If there are no plug-ins registered for the message, the operation will complete without an error.
  2. If the error is occurring in a custom client, you can modify your code so that it doesn't attempt to perform the work in a single operation. Instead, write code to retrieve the data in smaller parts.

Error: The given key was not present in the dictionary

Common Data Service frequently uses classes derived from the abstract DataCollection<TKey,TValue> class that represents a collection of keys and values. For example, with plug-ins the IExecutionContext.InputParameters property is a ParameterCollection derived from the DataCollection<TKey,TValue> class. These classes are essentially dictionary objects where you access a specific value using the key name.

Error codes

This error occurs when the key value in code doesn't exist in the collection. This is a run-time error rather a platform error. When this error occurs within a plug-in, the error code will depend on whether the error was caught.

If the developer caught the exception and returned an InvalidPluginExecutionException as described in Handle exceptions in plug-ins, the following error will be returned:

Error Code: -2147220891
Error Message: ISV code aborted the operation.

However, with this error it is common that the developer doesn't catch it properly and the following error will be returned:

Error Code: -2147220956
Error Message: An unexpected error occurred from ISV code.

Note

"ISV" stands for Independent Software Vendor.

Causes

This error frequently occurs at design time and can be due to a misspelling or using the incorrect casing. The key values are case sensitive.

At run-time the error is frequently due to the developer assuming that the value will be present when it isn't. For example, in a plug-in that is registered for the update of an entity, only those values which are changed will be included in the Entity.Attributes collection.

Prevention

To prevent this error you must check that the key exists before attempting to use it to access a value.

For example, when accessing an entity attribute, you can use the Entity.Contains(String) method to check whether an attribute exists in an entity as shown in the following code.

// Obtain the execution context from the service provider.  
IPluginExecutionContext context = (IPluginExecutionContext)
    serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.  
if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
    {
    // Obtain the target entity from the input parameters.  
    Entity entity = (Entity)context.InputParameters["Target"];

    //Check whether the name attribute exists.
    if(entity.Contains("name"))
    {
        string name = entity["name"];
    }

Some developers use the Entity.GetAttributeValue<T>(String) method to avoid this error when accessing entity attributes, but be aware that this method will return the default value of the type if the attribute doesn't exist. If the default value is null, this works as expected. But if the default value doesn't return null, such as with a DateTime, the value returned will be 1/1/0001 00:00 rather than null.