{"record":{"id":"a1baf93e8ca1e399","repo":"elsa-workflows/elsa-core","slug":"bpmnerrorcodes-exportnotimported","errorCode":"BpmnErrorCodes.ExportNotImported","errorMessage":"Workflow definition '{definition.DefinitionId}' does not currently carry BPMN source, so it cannot be exported as BPMN 2.0 XML. Either it was never imported from a BPMN document, or a later save replaced its custom properties wholesale and removed the '{SourceXmlCustomPropertyKey}' entry as a side effect of editing something else.","messagePattern":"Workflow definition '(.+?)' does not currently carry BPMN source, so it cannot be exported as BPMN 2\\.0 XML\\. Either it was never imported from a BPMN document, or a later save replaced its custom properties wholesale and removed the '(.+?)' entry as a side effect of editing something else\\.","errorType":"exception","errorClass":"BpmnExportUnavailableException","httpStatus":422,"severity":"error","filePath":"src/modules/Elsa.Bpmn.Interchange/Services/BpmnInterchangeDocumentService.cs","lineNumber":790,"sourceCode":"\n    /// <summary>The BPMN <c>calledElement</c> a call activity element carries, kept by the reader for round-trip.</summary>\n    private static string? CalledElementOf(BpmnElement element) =>\n        element.Properties.TryGetValue(BpmnXmlReader.CalledElementPropertyKey, out var calledElement) ? calledElement : null;\n\n    /// <summary>\n    /// The BPMN source a workflow definition was imported from, refusing rather than guessing when it is missing or\n    /// no longer trustworthy. See this type's remarks for what \"missing\" and \"stale\" mean and why each gets its own\n    /// message.\n    /// </summary>\n    /// <exception cref=\"BpmnExportUnavailableException\">\n    /// The definition does not currently carry BPMN source, or it does but the definition has changed since the\n    /// source was recorded.\n    /// </exception>\n    private static string ResolveSourceXml(WorkflowDefinition definition)\n    {\n        if (!definition.CustomProperties.TryGetValue<string>(SourceXmlCustomPropertyKey, out var xml) || string.IsNullOrEmpty(xml))\n        {\n            throw new BpmnExportUnavailableException(\n                $\"Workflow definition '{definition.DefinitionId}' does not currently carry BPMN source, so it cannot be exported as BPMN 2.0 XML. \"\n                + \"Either it was never imported from a BPMN document, or a later save replaced its custom properties wholesale and removed the \"\n                + $\"'{SourceXmlCustomPropertyKey}' entry as a side effect of editing something else.\",\n                BpmnExportUnavailableReason.NotImported);\n        }\n\n        if (!definition.CustomProperties.TryGetValue<int>(SourceVersionCustomPropertyKey, out var sourceVersion))\n        {\n            // Distinct from both other refusals: this is not \"never imported\" (the source text is right there) and\n            // not \"stale\" (there is no version to compare against yet). ImportAsync writes SourceXmlCustomPropertyKey\n            // and SourceVersionCustomPropertyKey together, in the single save described in its remarks, so this path\n            // is not reachable through import itself; it is kept as a defence against the same combination arising\n            // some other way — e.g. custom properties edited or migrated directly, outside ImportAsync — where\n            // \"whether the source still matches\" cannot be verified without a version to compare against.\n            throw new BpmnExportUnavailableException(\n                $\"Workflow definition '{definition.DefinitionId}' carries BPMN source, but not the definition version it was recorded against, so \"\n                + \"whether that source still matches this definition cannot be verified. It does not mean this definition was never imported from \"\n                + \"BPMN, and it does not mean the source is stale — there is simply no version recorded to compare against. Re-import the document to \"","sourceCodeStart":772,"sourceCodeEnd":808,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Bpmn.Interchange/Services/BpmnInterchangeDocumentService.cs#L772-L808","documentation":"ResolveSourceXml refuses export with BpmnExportUnavailableException (reason NotImported) when the definition's CustomProperties contain no non-empty SourceXmlCustomPropertyKey. Export requires the original BPMN XML recorded at import time; without it the definition cannot be rendered back to BPMN 2.0 XML. The message distinguishes 'never imported' from a later wholesale custom-properties save that removed the key.","triggerScenarios":"Calling Export on a definition that (a) was created natively and never imported from a BPMN document, or (b) had its CustomProperties overwritten by a save that replaced them wholesale, dropping SourceXmlCustomPropertyKey.","commonSituations":"Editing the workflow via a generic designer/save API that rewrites custom properties, copying definitions between environments without custom properties, or exporting a definition created from scratch instead of imported.","solutions":["Import the workflow from a BPMN document via the BPMN interchange import endpoint so SourceXmlCustomPropertyKey is recorded","If a save dropped the key, re-save the definition through the BPMN import path or restore the custom property containing the source XML","For natively-created definitions, use the appropriate (non-BPMN) export mechanism instead"],"exampleFix":"// before\nvar xml = bpmnService.Export(definitionId); // throws if never imported\n// after\nvar def = await definitions.FindAsync(handle);\nif (!def.CustomProperties.ContainsKey(BpmnErrorCodes.SourceXmlCustomPropertyKey))\n    await bpmnService.ImportAsync(def.DefinitionId, bpmnDocument);\nvar xml = bpmnService.Export(def.DefinitionId);","handlingStrategy":"try-catch","validationCode":"var imported = definition.CustomProperties.TryGetValue<string>(SourceXmlCustomPropertyKey, out var xml) && !string.IsNullOrEmpty(xml);\nif (!imported) throw new InvalidOperationException(\"Definition has no BPMN source; import first\");","typeGuard":null,"tryCatchPattern":"try { var xml = service.Export(id); }\ncatch (BpmnExportUnavailableException ex) when (ex.Reason == BpmnExportUnavailableReason.NotImported) { /* use non-BPMN export or import first */ }","preventionTips":["Only use BPMN export for definitions actually imported from BPMN","Avoid wholesale CustomProperties overwrites; merge dictionaries instead","Track which definitions are BPMN-managed in your tooling"],"tags":["bpmn","export","custom-properties","not-imported"],"backgroundTag":"bpmn-source-missing","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}