Troubleshooting custom activity types and Marketing Automation

Below are some tips for debugging and troubleshooting customisations in your Sitecore Marketing Automation plans. See also the slides from my recent Sitecore Symposium presentation “Automate Everything!” and the supporting code on GitHub.


  • Activity Properties must be PUBLIC to be populated
    • In your .NET class, ensure that the properties representing your Activity Type Parameters are public, otherwise the values will not be able to be set by the MA UI or read by the Automation Engine. (e.g. Message property in this file)
  • Ensure your activity ID is the same across:
    • Your config patch
    • Sitecore Activity Descriptor item
    • Angular package (lower case)
  • Watch out for DLL hell
    • Be careful which package versions you use in your .NET activity class or injected services. The dependencies that you use must be compatible with the Sitecore CM server and the Automation Engine.
  • If using custom facets, you have to include a config so that the Engine knows about them (contact loader XML)
  • Patch files MUST have the filename format sc.<name>.xml.
    • For example: sc.MarketingAutomation.ContactLoader.xml
  • MA engine won’t recycle on XML changes.
    • Unlike a typical Sitecore config, the Automation Engine will not recycle when you update when you edit or add an XML config file. You need to restart the service or WebJob manually for the changes to be picked up.
  • Activity not showing in the MA UI?
    • Make sure you have an icon in your Activity Type Descriptor
    • Check the XHR request in your browser network tab – the error will be in the HTTP response.
    • Ensure the DLL and plugin JS have been deployed to the Content Management server and that your Activity Type Descriptor is using the correct DLL reference.
  • Activity Type Parameters – set the editor and ObjectType (e.g. System.String).
    • This avoids getting quotes around your parameter values inbound and outbound

Some other tips

Sitecore kernel

You don’t have access to the Sitecore kernel or context database in the Automation Engine. The engine runs independently of Sitecore XM, so you cannot retrieve Sitecore items and you should not try to do so. And besides, you don’t have the connection strings in the engine config. You can use the built-in API’s to access some kinds of content.


Logging in the MA engine is completely different to “traditional” Sitecore logging which uses Log4Net. The Automation Engine uses the Ilogger interface from Microsoft.Extensions.Logging.

Log files are separate to the Sitecore logs:

Debugging your code

Attach to the MA engine for debugging in your local instance. The service will probably be named maengine. Make sure that you pick the right one, since you might have more than one MA engine service running. Mouse over the “maengine” process name in the list and it should show the file path to the maengine.exe file.

In PaaS, consult the Webjobs dashboard (as per previous section above). errors will be output to the console:


Sitecore automation plans are just Sitecore items. You can serialise MA plans and deploy them via Unicorn, TDS, and Sitecore packages.

Plans are stored in buckets under:
/sitecore/system/Marketing Control Panel/Automation Plans

Activity Type Descriptors are stored in:
/sitecore/system/Settings/Analytics/Marketing Automation/Activity Types

Predicate definitions are stored in a folder of your choosing under:
e.g. in the “XConnect – Marketing Automation” folder

Update: if you get this error below in the XHR calls from the MA UI, then you are missing an icon on your Sitecore Activity Descriptor item.

message: “An error has occurred.”,
exceptionMessage: “The ‘ObjectContent1' type failed to serialize the response body for content type 'application/json'.", exceptionType: "System.InvalidOperationException", stackTrace: null, innerException: { message: "An error has occurred.", exceptionMessage: "Value cannot be null. Parameter name: image", exceptionType: "System.ArgumentNullException", stackTrace: " at Sitecore.Diagnostics.Error.AssertString(String argument, String name, Boolean allowEmpty) at Sitecore.Resources.Images.GetThemedImageSource(String image) at Sitecore.Marketing.Automation.Extensions.ActivityDescriptorViewModelExtensions.ToViewModel(IActivityDescriptor activityDescriptor) at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding) at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding) at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.WebHost.HttpControllerHandler.d__22.MoveNext()”