XConnect.Operations.FacetOperationException: AlreadyExists

Had an issue with contact interactions not saving as expected and looked in Xconnect instance log file and saw this error message.

Sitecore.XConnect.Operations.FacetOperationException: Operation #0, AlreadyExists, Contact <contactId>, Classification

We have some custom code that saves and updates contacts so I started digging to find the culprit.

I stumbled upon this know issue in Sitecore 9.x, which I was using, that is fixed in Siteore 10.
https://support.sitecore.com/kb?id=kb_article_view&amp;sysparm_article=KB0397292

But before I installed the package from the Known Issue, I wanted to make sure my custom code was solid and that I wasn’t making any errors there myself. Spoiler, it was, so take a look in your custom code before (if any).

My issue was that I misunderstood the process of how contacts are retrieved with the xConnect API works. I thought I could just get a contact by some Facet, like an email, and then I would get that contact with all it’s Facets and values.

In my case I wanted to set the “Personal” Facet if it was null and then save it.
But I got the contact without the ExpandOptions{PersonalInformation.DefaultFacetKey… which meant that the Facet “Personal” was always null.
So when I submitted it, it threw an error because I was trying to add a Facet that already existed on the contact. With the updated ExpandOptions like below, I was now getting the correct Facets on the contact and it worked like a charm.

var identifier = new IdentifiedContactReference(Constants.EmailSource, email);
var contact = context.Get(identifier, new ExpandOptions(PersonalInformation.DefaultFacetKey, EmailAddressList.DefaultFacetKey));

if (contact.GetFacet<PersonalInformation>(PersonalInformation.DefaultFacetKey) == null)
{
    PersonalInformation personalInfoFacet = new PersonalInformation() {FirstName = firstname, LastName = lastname};
    context.SetFacet(existingContact, PersonalInformation.DefaultFacetKey, personalInfoFacet);
}

context.Submit();

Hope this helps bring some clarity as it did for me! 🙂