Sitecore Solr setup: Document is missing mandatory uniqueKey field: id

While reconfiguring Sitecore (8.2u5) to use Solr (6.6.1) instead of Lucene, I came across the following error:

Document is missing mandatory uniqueKey field: id

In full:

Job started: Index_Update_IndexName=sitecore_master_index|#Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> SolrNet.Exceptions.SolrConnectionException: <?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader"><int name="status">400</int><int name="QTime">1</int></lst><lst name="error"><lst name="metadata"><str name="error-class">org.apache.solr.common.SolrException</str><str name="root-error-class">org.apache.solr.common.SolrException</str></lst><str name="msg">Document is missing mandatory uniqueKey field: id</str><int name="code">400</int></lst>
</response>
 ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
 at System.Net.HttpWebRequest.GetResponse()
 at HttpWebAdapters.Adapters.HttpWebRequestAdapter.GetResponse()
 at SolrNet.Impl.SolrConnection.GetResponse(IHttpWebRequest request)
 at SolrNet.Impl.SolrConnection.PostStream(String relativeUrl, String contentType, Stream content, IEnumerable`1 parameters)
 --- End of inner exception stack trace ---
 at SolrNet.Impl.SolrConnection.PostStream(String relativeUrl, String contentType, Stream content, IEnumerable`1 parameters)
 at SolrNet.Impl.SolrConnection.Post(String relativeUrl, String s)

Here’s what to check.

  • Does your Solr core index config directory have a file called managed-schema? If so, delete this file and reload the core. Solr will be ignoring any changes you’re making to schema.xml and using managed-schema instead. Deleting this file and reloading the core will pick up your latest version of schema.xml

 

Delete this file

solr-error

 

Reload the core

solr-rebuild

 

Rebuild the index in Sitecore and the error should be gone. 

solr-reindex

Digging into Unicorn configs in Sitecore Habitat

Sitecore Habitat ships with Unicorn as the serialization utility of choice. Unicorn works in the background during the development of a Sitecore implementation and writes out a YAML copy of templates, renderings and other Sitecore items to disk.
You can then add these YAML (.yml) files to your version control repository, merge changes with other developers and ensure they are picked up / deployed to target environments as part of your continuous integration (CI) pipeline.

In Habitat, we bundle a Unicorn-specific configuration file with each module – in line with the Helix principle that any assets relating to a module should be bundled and deployed with that module.

If we had a feature module called ‘Car’, we’d create a config patch in App_Config/Include/Feature called Feature.Car.Serialization.Config

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
 <sitecore>
  <unicorn>
   <configurations>
    <configuration name="Feature.Car" description="Feature Car" dependencies="Foundation.*" extends="Helix.Feature">
     <rolePredicate>
      <include domain="modules" pattern="^Feature Car .*$" />
     </rolePredicate>
    </configuration>
   </configurations>
  </unicorn>
 </sitecore>
</configuration>

The key line setting up this configuration file is:

<configuration name="Feature.Car" description="Feature Car" dependencies="Foundation.*" extends="Helix.Feature">

Aside from the obvious name and description, dependencies tells Unicorn to run other configurations before this one (in our case, run any other configuration named Foundation.* first. Extends allows us to inherit from a parent config, Helix.Feature. This is a great feature which removes unnecessary code duplication in Helix solutions (which can have hundreds of modules!)

With this simple config (which extends the Helix.Feature abstract configuration), Unicorn will sync any Sitecore definition items under any folder called /Feature/Car in Sitecore. Happily, the Helix.Feature abstract config will ensure that Unicorn puts its .yml files alongside the rest of your source code for the Car module. We can track down the configuration line which determines the serialization location in Unicorn.Helix.config:

<configuration name="Helix.Feature" abstract="true" extends="Helix.Base">
 <predicate>
   <include name="Templates" database="master" path="/sitecore/templates/$(layer)/$(module)" />
   <include name="Renderings" database="master" path="/sitecore/layout/renderings/$(layer)/$(module)" />
   <include name="Media" database="master" path="/sitecore/media library/$(layer)/$(module)" />
  </predicate>
</configuration>

 

Read more about Unicorn configuration at Kam’s blog.