elsa-workflows/elsa-core · error · BpmnInterchangeException
Subprocess element ' ' of process ' ' carries no…
Error message
Subprocess element '{subprocess.ElementId}' of process '{process.ProcessId}' carries no bindingRef, so the body stored for it cannot be written back with it. The document does not carry a subprocess's body, so writing it without one would silently empty the subprocess. Send the element with the bindingRef the document GET returned. What it means
When re-importing a document, StoredNestedScopesStillDeclaredBy carries across stored subprocess bodies to the new document. If an incoming subprocess element carries no bindingRef, the stored body cannot be reattached — writing it without one would silently empty the subprocess — so BpmnInterchangeException is thrown. The document format deliberately excludes subprocess bodies, so bindingRef is the only way to link the element back to its stored body.
Solutions
- Send the subprocess element with the bindingRef exactly as the document GET returned it
- Start each edit from the document returned by GET rather than hand-crafted XML
- Extend your XML transformations to preserve the bindingRef attribute on subprocess elements
Example fix
// before <subProcess id="Sub1"/> // after <subProcess id="Sub1" bindingRef="stored-body-ref-from-GET"/>
Defensive patterns
Strategy: validation
Validate before calling
foreach (var sp in document.Processes.SelectMany(p => p.Subprocesses))
if (sp.BindingRef is null) throw new InvalidOperationException($"Subprocess {sp.ElementId} is missing bindingRef"); Try / catch
try { await service.ImportAsync(id, doc); }
catch (BpmnInterchangeException ex) when (ex.Message.Contains("bindingRef")) { restoreBindingRefsFromGetResponse(); } Prevention
- Always edit from the GET response document, never hand-built XML
- Preserve all attributes (especially bindingRef) in XML transformations
- Add a schema check that subprocesses with stored bodies carry bindingRef before import
When it happens
Trigger: PUTting/importing a BPMN document in which a subprocess element (subprocess.ElementId within process.ProcessId) that has a stored body omits bindingRef — e.g. the client hand-built the XML instead of echoing the GET response.
Common situations: Manually authoring or transforming the BPMN XML and dropping the bindingRef attribute, running an XML transformation/normalizer that strips unknown attributes, or copying subprocess elements between documents without their bindingRefs.
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
- An < : > element declares no ' ', so there is nothing to…
- An < : > element of the ' ' binding declares no ' '.
- The ' ' binding declares the input ' ' more than once. Each…
- The ' ' binding declares , which ' ' does not have.
- BPMN element ' ' ( ) of process ' ' carries an < : >…
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/fd766316a02966b2.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Bpmn.Interchange/Services/BpmnInterchangeDocumentService.cs:670
.Where(element => element.LoopCharacteristics is not null)
.Select(element => element.ElementId)
.ToHashSet(StringComparer.Ordinal);
var kept = new List<BpmnWorkBinding>();
foreach (var process in document.Processes)
{
foreach (var subprocess in process.Elements.Where(element => element.ElementType == BpmnElementTypes.SubProcess))
{
// Last match wins, as it does inside the writer itself, should a malformed document repeat an id.
var body = storedBindings.OfType<BpmnWorkBinding.NestedProcess>().LastOrDefault(nested => nested.ElementId == subprocess.ElementId);
if (body is null)
continue;
if (subprocess.BindingRef is null)
{
throw new BpmnInterchangeException(
$"Subprocess element '{subprocess.ElementId}' of process '{process.ProcessId}' carries no bindingRef, so the body stored for it cannot be written back with it. "
+ "The document does not carry a subprocess's body, so writing it without one would silently empty the subprocess. Send the element with the bindingRef the document GET returned.");
}
kept.Add(HandOver(body) with { BindingRef = subprocess.BindingRef });
KeepEverythingBoundInside(body.ElementId);
}
}
return kept;
// A nested process's bindings name the subprocess element's id as their process (see BpmnWorkBinding.ProcessId).
void KeepEverythingBoundInside(string scopeId)
{
foreach (var binding in storedBindings.Where(binding => binding.ProcessId == scopeId))
{
if (binding is not BpmnWorkBinding.NestedProcess nested)
{View on GitHub (pinned to fe9217bdfa)