apache/incubator-seata · error · Error

Two or more start states, ${target} and ${definitions.StartS

Error message

Two or more start states, ${target} and ${definitions.StartState}

What it means

Thrown by SagaExporter.parseEdge when a second edge with no resolvable source state is exported while definitions.StartState is already set. In the Seata Saga state machine designer, an edge whose source shape has no Name is treated as the edge coming from the implicit start state; only one such edge is allowed per state machine. The message names both offending targets.

Source

Thrown at saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js:60

SagaExporter.prototype.parseEdge = function (definitions, edge) {
  const { businessObject } = edge;
  const elementJson = businessObject.exportJson();

  let { source } = elementJson.style;
  let { target } = elementJson.style;

  if (edge.source && edge.source.businessObject && edge.source.businessObject.Name) {
    source = edge.source.businessObject.Name;
    elementJson.style.source = source;
  }
  if (edge.target && edge.target.businessObject && edge.target.businessObject.Name) {
    target = edge.target.businessObject.Name;
    elementJson.style.target = target;
  }

  if (!source) {
    if (definitions.StartState) {
      throw new Error(`Two or more start states, ${target} and ${definitions.StartState}`);
    } else {
      definitions.StartState = target;
      if (definitions.edge === undefined) {
        definitions.edge = {};
      }
      assign(definitions.edge, elementJson);
    }
  } else {
    const stateRef = definitions.States[source];

    if (!stateRef) {
      throw new Error(`Export failed: Unable to resolve source state '${source}' for edge targeting '${target}'.`);
    }

    switch (businessObject.Type) {
      case 'ChoiceEntry':
        if (!stateRef.Choices) {
          stateRef.Choices = [];

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Open the diagram in the designer and make sure exactly one edge originates from the start marker; delete the duplicate start edge.
  2. Click each suspicious connection and verify its source shape is attached and has a non-empty Name property.
  3. If a state was renamed, reconnect the dangling edge to the correct named state before exporting.
  4. As a last resort, edit the underlying JSON/XML of the diagram and remove the extra start edge, then re-import.

Example fix

// before (diagram): two edges with source === undefined
// StartState --> FirstTask
// (dangling edge) --> SecondTask

// after: delete the dangling edge so only one source-less edge remains, then re-export
Defensive patterns

Strategy: validation

Validate before calling

function hasSingleStartEdge(elementRegistry) {
  const edges = elementRegistry.getAll().filter(el => el.businessObject instanceof Edge);
  const startEdges = edges.filter(e => !(e.source && e.source.businessObject && e.source.businessObject.Name));
  return startEdges.length <= 1;
}
// call before exporter.export()

Type guard

function isNamedSource(edge) {
  return Boolean(edge && edge.source && edge.source.businessObject && edge.source.businessObject.Name);
}

Try / catch

try {
  exporter.export();
} catch (e) {
  if (/Two or more start states/.test(e.message)) {
    // prompt user to remove the duplicate start edge, listing both names from the message
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling SagaExporter.export() on a diagram that contains two or more edges whose source element is missing or whose businessObject.Name is empty/undefined (e.g. two start-state transitions, or an edge detached from its source shape in the bpmn-js canvas).

Common situations: Users drag a second 'StartState' node into the diagram, copy-paste a start marker, or delete/rename a state so an edge loses its source Name, then hit Save/Export in the designer.

Related errors


AI-assisted analysis of apache/incubator-seata@e01f97c6db (2026-08-14). Data as JSON: /api/errors/8140d9a734f36582. Report an issue: GitHub.