Handling exceptions

This topic describes the exceptions that can be returned by xConnect and when they are likely to occur.

XdbUnavailableException

An XdbUnavailableException exception indicates that the xConnect services is unavailable or that the request has timed out. The XdbCollectionUnavailableException and XdbSearchUnavailableException exceptions both inherit XdbUnavailableException.

XdbExecutionException

xConnect throws an XdbExecutionException when one or more operations in a batch fails to execute. Use client.GetOperations() to select the specific operations that failed. The following example selects any operations that failed because the PhoneNumberList facet already exists.

using Sitecore.XConnect.Collection.Model;
using Sitecore.XConnect.Operations;
using System;
using System.Threading.Tasks;
using Sitecore.XConnect.Client.Operations;
using System.Linq;
using Sitecore.XConnect.Schema;
using Sitecore.XConnect;
using Sitecore.XConnect.Client;

namespace Documentation
{
    public class CatchingExceptions
    {
        public async void ExampleAsync()
        {
            using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
            {
                try
                {
                    // Get contact
                    var reference = new Sitecore.XConnect.ContactReference(Guid.Parse("B9814105-1F45-E611-82E6-34E6D7117DCB"));

                    Task<Sitecore.XConnect.Contact> contactTask = client.GetAsync<Sitecore.XConnect.Contact>(reference, new Sitecore.XConnect.ContactExpandOptions(Sitecore.XConnect.Collection.Model.CollectionModel.FacetKeys.PhoneNumberList) { });

                    Sitecore.XConnect.Contact contact = await contactTask;

                    // Update some properties on an existing facet
                    PhoneNumberList phoneNumberList = contact.PhoneNumbers();

                    phoneNumberList.PreferredKey = "Work";
                    phoneNumberList.PreferredPhoneNumber = new PhoneNumber("44", "55555555") { Extension = "1234" };

                    // Set updated facet
                    client.SetPhoneNumbers(contact, phoneNumberList);

                    // Submit changes
                    await client.SubmitAsync();
                }
                catch (XdbExecutionException ex)
                {
                    // Get any operations that failed
                    var operations = ex.GetOperations(client)
                        .Where(x => x.Status == XdbOperationStatus.Failed);

                    foreach (var ops in operations)
                    {
                        if (ops is SetFacetOperation<PhoneNumberList>)
                        {
                            var phoneOps = ops as SetFacetOperation<PhoneNumberList>;

                            if (phoneOps.Result.Status == SaveResultStatus.AlreadyExists)
                            {
                                // LOG: This contat already has a PhoneNumberList facet
                            }
                        }
                    }
                }
            }
        }

        public void ExampleSync()
        {
            using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
            {
                try
                {
                    // Get contact
                    var reference = new Sitecore.XConnect.ContactReference(Guid.Parse("B9814105-1F45-E611-82E6-34E6D7117DCB"));

                    Contact contact = client.Get<Sitecore.XConnect.Contact>(reference, new Sitecore.XConnect.ContactExpandOptions(Sitecore.XConnect.Collection.Model.CollectionModel.FacetKeys.PhoneNumberList) { });

                    // Update some properties on an existing facet
                    PhoneNumberList phoneNumberList = contact.PhoneNumbers();

                    phoneNumberList.PreferredKey = "Work";
                    phoneNumberList.PreferredPhoneNumber = new PhoneNumber("44", "55555555") { Extension = "1234" };

                    // Set updated facet
                    client.SetPhoneNumbers(contact, phoneNumberList);

                    // Submit changes
                    client.Submit();
                }
                catch (XdbExecutionException ex)
                {
                    // Get any operations that failed
                    var operations = ex.GetOperations(client)
                        .Where(x => x.Status == XdbOperationStatus.Failed);

                    foreach (var ops in operations)
                    {
                        if (ops is SetFacetOperation<PhoneNumberList>)
                        {
                            var phoneOps = ops as SetFacetOperation<PhoneNumberList>;

                            if (phoneOps.Result.Status == SaveResultStatus.AlreadyExists)
                            {
                                // LOG: This contat already has a PhoneNumberList facet
                            }
                        }
                    }
                }
            }
        }
    }
}
  • The Status property is available on all operations - XdbOperationStatus.Failed indicates a failed operation

  • Result.Status property is available on the SetFacetOperation and AddContactIdentifier operations - the Result property may be null if a connection error prevented the operation from being executed

  • Every operation has a nested Exception property

Retrying operations after an XdbExecutionException

You can retry a failed operation by adding it to the client using the client.RegisterOperation() method and re-submitting the batch. This is useful if an operation failed due to a connectivity issue.

Note

If an operation failed due to a concurrency issue, refer to the concurrency topic.

In the following example, an operation is retried after xConnect returned a XdbExecutionException, indicating that one or more operations failed:

catch (XdbExecutionException ex)
{
    // Get any operations that failed
    var operations = ex.GetOperations(client)
        .Where(x => x.Status == XdbOperationStatus.Failed);

    foreach (var ops in operations)
    {
        client.RegisterOperation(ops);
    }

    client.SubmitAsync();
}