elsa-workflows/elsa-core · error · BpmnBindingException

An < : > element declares no ' ', so there is nothing to…

Error message

An <{NamespacePrefix}:{BindingElementName}> element declares no '{ActivityTypeAttributeName}', so there is nothing to build.

What it means

BpmnActivityBindingFormat.Read parses an Elsa extension element in a BPMN model and requires the 'activity-type' attribute to know which Elsa activity to construct. When the element has no such attribute there is nothing to build, so it throws BpmnBindingException. This is a fail-fast validation of malformed BPMN interchange payloads.

Solutions

  1. Add the missing activity-type attribute (the one named by ActivityTypeAttributeName under the Elsa namespace) to the element.
  2. Validate the BPMN file against the expected Elsa interchange schema before import.
  3. Check the element's namespace prefix matches the configured NamespacePrefix so attributes resolve.
  4. Regenerate/export the diagram from the original authoring tool rather than hand-editing XML.

Example fix

// before
<elsa:activity-binding>
  <elsa:input name="Message" value="Hello" />
</elsa:activity-binding>

// after
<elsa:activity-binding activity-type="Elsa.Http:WriteHttpResponse">
  <elsa:input name="Content" value="Hello" />
</elsa:activity-binding>
Defensive patterns

Strategy: validation

Validate before calling

foreach (var el in bpmnDoc.Descendants().Where(e => e.Name.LocalName == "activity-binding"))
    if (el.Attributes().All(a => a.Name.LocalName != "activity-type"))
        throw new InvalidOperationException($"Element {el.Name.LocalName} at line {((IXmlLineInfo)el).LineNumber} is missing 'activity-type'.");

Try / catch

try
{
    var activity = bindingFormat.Read(element);
}
catch (BpmnBindingException ex)
{
    logger.LogError(ex, "Malformed BPMN activity binding at {ElementName}", element.Name);
}

Prevention

When it happens

Trigger: Importing/parsing a BPMN document whose extension element (e.g., <elsa:activity-binding>) lacks the activity-type attribute — BpmnBindingFormat.Read hits AttributeOf(element, ActivityTypeAttributeName) returning null.

Common situations: Hand-authored or tool-exported BPMN where the custom extension attributes were stripped or misspelled (wrong namespace prefix, wrong attribute name); XML copy-paste between diagrams; an exporter version that predates the attribute convention.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/5591aae90d4adc31. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Bpmn.Interchange/Binding/BpmnActivityBindingFormat.cs:191

            .OrderBy(input => input.Name, StringComparer.Ordinal)
            .Select(input => new BpmnExtensionElement(InputQName, [Attribute(InputNameAttributeName, input.Name)], null, activitySerializer.Serialize(input.Value!)))
            .ToList();

        return new(BindingQName, [Attribute(ActivityTypeAttributeName, activity.Type)], inputs);
    }

    /// <summary>
    /// The activity a binding element declares, built through Elsa's own activity serializer so that it is
    /// indistinguishable from the same activity loaded out of a stored workflow definition.
    /// </summary>
    /// <exception cref="BpmnBindingException">
    /// The element is malformed, names an activity type nothing registered, or names an input the activity type does
    /// not declare.
    /// </exception>
    public IActivity Read(BpmnExtensionElement element)
    {
        var activityType = AttributeOf(element, ActivityTypeAttributeName)
                           ?? throw new BpmnBindingException($"An <{NamespacePrefix}:{BindingElementName}> element declares no '{ActivityTypeAttributeName}', so there is nothing to build.");

        var activityJson = new JsonObject
        {
            ["type"] = activityType
        };

        // Every name seen so far, in the order the document declares them, so a second <elsa:input> with the same
        // name is refused rather than silently overwriting activityJson[name] and leaving the earlier one's
        // configuration invisible.
        var seenInputNames = new List<string>();
        var seenInputNameSet = new HashSet<string>(StringComparer.Ordinal);

        foreach (var input in element.Children.Where(child => child.Name == InputQName))
        {
            var name = AttributeOf(input, InputNameAttributeName)
                       ?? throw new BpmnBindingException($"An <{NamespacePrefix}:{InputElementName}> element of the '{activityType}' binding declares no '{InputNameAttributeName}'.");

            if (!seenInputNameSet.Add(name))

View on GitHub (pinned to fe9217bdfa)