elsa-workflows/elsa-core · error · BpmnBindingException
The binding to activity type
Error message
The binding to activity type '{activityType}' could not be deserialized: {exception.Message} What it means
The binding's assembled input JSON could not be deserialized into the target Elsa activity. Elsa's activity serializer threw a JsonException or NotSupportedException, and the binder rethrows it as a BpmnBindingException naming the activity type.
Solutions
- Read the inner message (appended to this error) to find which JSON member failed, then correct that input's JSON value in the binding to match the activity property's type.
- Check the activity type's declared input properties and ensure each JSON value matches (objects for complex types, proper enum strings, etc.).
- If a module upgrade changed a property's type, update the binding inputs to the new shape.
Example fix
// before <elsa:input name="Recipients">"a@b.c"</elsa:input> // activity expects an array // after <elsa:input name="Recipients">["a@b.c"]</elsa:input>
Defensive patterns
Strategy: validation
Validate before calling
foreach (var raw in inputElements)
{
var text = raw.Value?.Trim();
if (!string.IsNullOrEmpty(text))
JsonNode.Parse(text); // throws early with position details
} Type guard
static bool IsValidJson(string? s)
{
if (string.IsNullOrWhiteSpace(s)) return true;
try { JsonNode.Parse(s); return true; } catch (JsonException) { return false; }
} Try / catch
try { await importer.ImportAsync(bpmn); }
catch (BpmnBindingException ex) when (ex.Message.Contains("could not be deserialized"))
{
logger.LogError(ex, "Binding JSON does not match the activity type shape.");
} Prevention
- Check the activity type's declared input property types before authoring bindings
- Re-validate bindings after upgrading the module that owns the activity type
- Keep JSON values well-formed and shape-correct (arrays, objects, enum strings)
When it happens
Trigger: BpmnActivityBindingFormat.Read calls activitySerializer.Deserialize(activityJson) and the serializer throws JsonException or NotSupportedException (e.g. a JSON value whose shape doesn't match the activity property type, or an unsupported type).
Common situations: A binding input value has the right JSON syntax but the wrong shape (string where object expected, number where enum string expected); input JSON is valid XML text but not the shape the activity expects; a module version changed the property type.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- Cannot deserialize to .
- Failed to deserialize
- Input ' ' of the ' ' binding does not hold valid JSON
- Expected number or string.
- Cannot convert to bool
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/7647c68639cd9cfa.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Bpmn.Interchange/Binding/BpmnActivityBindingFormat.cs:224
var name = AttributeOf(input, InputNameAttributeName)
?? throw new BpmnBindingException($"An <{NamespacePrefix}:{InputElementName}> element of the '{activityType}' binding declares no '{InputNameAttributeName}'.");
if (!seenInputNameSet.Add(name))
throw new BpmnBindingException($"The '{activityType}' binding declares the input '{name}' more than once. Each <{NamespacePrefix}:{InputElementName}> must name a distinct input.");
seenInputNames.Add(name);
activityJson[name] = Parse(input.Value, name, activityType);
}
IActivity activity;
try
{
activity = activitySerializer.Deserialize(activityJson.ToJsonString());
}
catch (Exception exception) when (exception is JsonException or NotSupportedException)
{
throw new BpmnBindingException($"The binding to activity type '{activityType}' could not be deserialized: {exception.Message}");
}
// Elsa's activity serializer answers an unregistered type with a NotFoundActivity rather than throwing, and
// that placeholder only fails once it executes — by which time the workflow has already started and the
// process is mid-flight. Refusing at bind time turns "this .bpmn needs a module you have not installed" into a
// sentence naming the type, at the point where someone can still do something about it.
if (activity is NotFoundActivity)
throw new BpmnBindingException($"The binding names activity type '{activityType}', which is not registered in this application. Install or enable the module providing it before importing this document.");
// Elsa's own JSON deserialization ignores a member the target type does not declare, so a mistyped or
// stale input name would otherwise import silently as an activity missing that configuration, with no
// diagnostic anywhere. IActivityDescriber.GetInputProperties is the same enumeration Write reads from and
// ActivityDescriptor.Inputs is built from, so a name is accepted here exactly when Write could have produced
// it.
if (seenInputNames.Count > 0)
{
var declaredInputNames = activityDescriber.GetInputProperties(activity.GetType())
.Select(property => JsonNamingPolicy.CamelCase.ConvertName(property.Name))View on GitHub (pinned to fe9217bdfa)