Sitecore Campaign Creator API 500 error caused by Sitecore Instance Manager
This issue occurs when I use
- Sitecore Instance Manager(SIM) 1.5 for
- Sitecore 8.2 Update 4 with
- Solr 5.1
- Using the automatic Sole config function of SIM
What happens is that after Sitecore is setup according to above and you go in to “Campaign Creator” (http://cm.local/sitecore/client/applications/CampaignManager/Dashboard), the loading gif will not go away and you can see the following url returned 500 error:
And from Sitecore logs, you can see below exception:
18364 2018:03:20 14:57:42 ERROR [Sitecore Services]: HTTP GETException System.InvalidCastException: Could not map index document field to property "Culture" on type Sitecore.Marketing.Search.IndexedCampaign : Could not convert value of type System.Collections.ArrayList to destination type System.Globalization.CultureInfo: Unable to cast object of type 'System.Collections.ArrayList' to type 'System.String'. ---> System.InvalidCastException: Could not convert value of type System.Collections.ArrayList to destination type System.Globalization.CultureInfo: Unable to cast object of type 'System.Collections.ArrayList' to type 'System.String'. ---> System.InvalidCastException: Unable to cast object of type 'System.Collections.ArrayList' to type 'System.String'.at Sitecore.ContentSearch.Converters.IndexFieldCultureInfoValueConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)at Sitecore.ContentSearch.Converters.IndexFieldStorageValueFormatter.ReadFromIndexStorage(Object indexValue, String fieldName, Type destinationType)--- End of inner exception stack trace ---at Sitecore.ContentSearch.Converters.IndexFieldStorageValueFormatter.ReadFromIndexStorage(Object indexValue, String fieldName, Type destinationType)at Sitecore.ContentSearch.DocumentTypeMapInfo.SetProperty(Object target, String propertyName, String documentFieldName, Object value)--- End of inner exception stack trace ---at Sitecore.ContentSearch.DocumentTypeMapInfo.SetProperty(Object target, String propertyName, String documentFieldName, Object value)at Sitecore.ContentSearch.DefaultDocumentMapper`1.MapFieldValuesToType[TElement](IDictionary`2 fieldValues, TElement result, DocumentTypeMapInfo documentTypeMapInfo)at Sitecore.ContentSearch.DefaultDocumentMapper`1.MapToType[TElement](TDocument document, SelectMethod selectMethod, IEnumerable`1 virtualFieldProcessors, IEnumerable`1 executionContexts, SearchSecurityOptions securityOptions)at Sitecore.ContentSearch.SolrProvider.SolrSearchResults`1.<GetSearchResults>d__21.MoveNext()at System.Linq.Buffer`1..ctor(IEnumerable`1 source)at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)at Sitecore.Marketing.Search.BaseDefinitionSearchProvider`2.Search[TSortByKey](SearchParameters`2 definitionSearchParameters)at Sitecore.Marketing.Campaigns.Services.Data.CampaignRepository.GetFilteredEntities(FilterEntity filter, Int32 pageIndex, Int32 pageSize)at Sitecore.Marketing.Campaigns.Services.Controllers.CampaignController.FetchEntities(FilterEntity filter, Int32 pageIndex, Int32 pageSize)at lambda_method(Closure , Object , Object[] )at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()--- End of stack trace from previous location where exception was thrown ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()
The direct cause is that the culture field in Sitecore_MarketingDefinitions_master is an array in Solr index but Sitecore expect it to be a string:
Continue from that, I noticed the difference in Solr Core's schema.xml for the index Sitecore_MarketingDefinitions_master that’s created by SIM’s Solr module VS the schema.xml created by Sitecore client:
The one on the top is from SIM, the one at the bottom is from Sitecore. This multiValued attribute looks so suspicious! So I removed the attribute and reloaded the core in Solr. The culture field is now no longer an array field (string field now as below) and the issue in Sitecore is gone.
Obviously I wanted to know why, why did SIM created that schema and can I trust it anymore?
Then I found this part of the code in SIM:https://github.com/Sitecore/Sitecore-Instance-Manager/search?utf8=%E2%9C%93&q=CollectionTemplate&type=
So it uses the same functionality that’s being used when you generate schema.xml using Sitecore Client, but instead of using the sample schema.xml from “basic_configs” folder, it uses the one from “data_driven_schema_configs”. So which one should be used?
In Sitecore official documentation
It doesn’t really specify which folder it gets schema.xml from since the screenshot is very old.
On the internet, in Sitecore Community documentation
It uses the one from “basic_configs” and only use “data_driven_schema_configs” for some additional setup.
I guess using “basic_configs” is definitely safer since that’s what everyone have been using and at least, it doesn’t have this issue… On SIM github README, it mentioned that the reason data_driven_schema_configs is used is because it has the language support required to index non-English text. I think I will raise an issue in Github to see if this is already considered. For now, this will be it.