{"record":{"id":"cc399bbc7453ec62","repo":"apache/incubator-seata","slug":"export-failed-unable-to-resolve-source-state-s","errorCode":null,"errorMessage":"Export failed: Unable to resolve source state '${source}' for edge targeting '${target}'.","messagePattern":"Export failed: Unable to resolve source state '(.+?)' for edge targeting '(.+?)'\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js","lineNumber":72,"sourceCode":"    target = edge.target.businessObject.Name;\n    elementJson.style.target = target;\n  }\n\n  if (!source) {\n    if (definitions.StartState) {\n      throw new Error(`Two or more start states, ${target} and ${definitions.StartState}`);\n    } else {\n      definitions.StartState = target;\n      if (definitions.edge === undefined) {\n        definitions.edge = {};\n      }\n      assign(definitions.edge, elementJson);\n    }\n  } else {\n    const stateRef = definitions.States[source];\n\n    if (!stateRef) {\n      throw new Error(`Export failed: Unable to resolve source state '${source}' for edge targeting '${target}'.`);\n    }\n\n    switch (businessObject.Type) {\n      case 'ChoiceEntry':\n        if (!stateRef.Choices) {\n          stateRef.Choices = [];\n        }\n        stateRef.Choices.push({\n          Expression: businessObject.Expression,\n          Next: target,\n        });\n        if (businessObject.Default) {\n          stateRef.Default = target;\n        }\n        stateRef.edge = assign(stateRef.edge || {}, { [target]: elementJson });\n        break;\n      case 'ExceptionMatch':\n        if (!stateRef.Catch) {","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/apache/incubator-seata/blob/e01f97c6db397165050caa6764020410c2c8199a/saga/seata-saga-statemachine-designer/src/modeling/SagaExporter.js#L54-L90","documentation":"Thrown by SagaExporter.parseEdge when an edge has a source Name but definitions.States has no entry for it. During export, every state is registered in definitions.States keyed by its Name (parseState); an edge referencing a source not in that map means the graph references a state the exporter never processed.","triggerScenarios":"Calling export() when an edge's source businessObject.Name refers to a state that was deleted, renamed after the edge was drawn, or whose businessObject is not an instance of the State spec class filtered in export().","commonSituations":"Renaming a state in the designer after connecting edges to it; deleting a state without deleting its edges; a corrupted or hand-edited diagram file where edge style.source does not match any state Name.","solutions":["Re-attach the failing edge to an existing, named state in the designer.","Check for leftover edges of deleted states (select-all around the area or inspect elementRegistry) and delete them.","If a state was renamed, update the edge source to the new Name (redraw the connection).","Inspect the diagram JSON and make sure every edge's style.source matches a States key exactly (case-sensitive)."],"exampleFix":"// before: state 'SubmitOrder' renamed to 'SubmitOrderTask', edge still points at old name\n// elementJson.style.source === 'SubmitOrder' -> definitions.States['SubmitOrder'] === undefined\n\n// after: redraw the edge from 'SubmitOrderTask' so style.source matches the state Name","handlingStrategy":"validation","validationCode":"function allEdgeSourcesResolve(elementRegistry) {\n  const stateNames = new Set(\n    elementRegistry.getAll()\n      .filter(el => el.businessObject instanceof State)\n      .map(el => el.businessObject.Name)\n  );\n  return elementRegistry.getAll()\n    .filter(el => el.businessObject instanceof Edge)\n    .every(e => !e.source || stateNames.has(e.source.businessObject && e.source.businessObject.Name));\n}","typeGuard":"function isResolvedState(definitions, name) {\n  return Boolean(name) && Object.prototype.hasOwnProperty.call(definitions.States, name);\n}","tryCatchPattern":"try {\n  exporter.export();\n} catch (e) {\n  if (/Unable to resolve source state/.test(e.message)) {\n    // extract source/target from message and highlight the dangling edge in the UI\n  }\n  throw e;\n}","preventionTips":["Delete edges together with the states they connect (designer should orphan-check on element delete).","Validate that every edge's style.source matches an existing state Name before saving.","Treat state renames as a refactor: update all referencing edges atomically."],"tags":["saga","statemachine","designer","export","dangling-reference"],"backgroundTag":null,"analyzedSha":"e01f97c6db397165050caa6764020410c2c8199a","analyzedAt":"2026-08-14T10:23:53.097Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}