{"record":{"id":"7c343a779c636867","repo":"Zie619/n8n-workflows","slug":"no-edi-message-found-in-input-please-provide-the","errorCode":null,"errorMessage":"No EDI message found in input. Please provide the EDI message in the \"ediMessage\" property.","messagePattern":"No EDI message found in input\\. Please provide the EDI message in the \"ediMessage\" property\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"workflows/Splitout/0793_Splitout_Code_Send_Triggered.json","lineNumber":1332,"sourceCode":"        \"simple\": false,\n        \"options\": {},\n        \"messageId\": \"={{ $json.id }}\",\n        \"operation\": \"get\"\n      },\n      \"notesInFlow\": true,\n      \"typeVersion\": 2.1,\n      \"notes\": \"This gmail node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"0346eabe-552a-47d8-ac9e-9619926d0242\",\n      \"name\": \"Parse EDI Message\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        -4660,\n        -860\n      ],\n      \"parameters\": {\n        \"jsCode\": \"// EDI Parser function for n8n JavaScript node\\nfunction parseEDI(ediMessage) {\\n  // Define the data structure to store parsed results\\n  const result = {\\n    interchangeHeader: {},\\n    messageHeader: {},\\n    orderDetails: {},\\n    dates: [],\\n    parties: [],\\n    lineItems: []\\n  };\\n  \\n  // Split the message into lines and remove empty lines\\n  const lines = ediMessage.split(\\\"'\\\").filter(line => line.trim().length > 0);\\n  \\n  // Parse each line\\n  let currentLineItem = null;\\n  \\n  for (const line of lines) {\\n    const segments = line.trim().split('+');\\n    const segmentName = segments[0];\\n    \\n    switch (segmentName) {\\n      case 'UNA':\\n        // Service String Advice - contains delimiter information\\n        break;\\n        \\n      case 'UNB':\\n        // Interchange Header\\n        // UNB+UNOC:3+SENDER_ID+RECEIVER_ID+240318:1200+ORDER54321\\n        result.interchangeHeader = {\\n          syntax: segments[1],\\n          senderId: segments[2],\\n          receiverId: segments[3],\\n          dateTime: segments[4]?.split(':')[0] || '',\\n          time: segments[4]?.split(':')[1] || '',\\n          controlReference: segments[5] || ''\\n        };\\n        break;\\n        \\n      case 'UNH':\\n        // Message Header\\n        // UNH+1+ORDERS:D:96A:UN\\n        if (segments.length > 2) {\\n          const messageParts = segments[2].split(':');\\n          result.messageHeader = {\\n            messageReference: segments[1],\\n            messageType: messageParts[0],\\n            messageVersion: messageParts[1],\\n            messageRelease: messageParts[2],\\n            controlAgency: messageParts[3]\\n          };\\n        }\\n        break;\\n        \\n      case 'BGM':\\n        // Beginning of Message\\n        // BGM+230+RT54321098+9\\n        result.orderDetails = {\\n          documentType: segments[1],\\n          documentNumber: segments[2],\\n          messageFunction: segments[3]\\n        };\\n        break;\\n        \\n      case 'DTM':\\n        // Date/Time/Period\\n        // DTM+137:20250319:102\\n        if (segments[1]) {\\n          const dateParts = segments[1].split(':');\\n          const dateObj = {\\n            qualifier: dateParts[0],\\n            date: dateParts[1],\\n            format: dateParts[2]\\n          };\\n          \\n          // Add human-readable description based on qualifier\\n          switch (dateParts[0]) {\\n            case '137':\\n              dateObj.description = 'Document Date';\\n              break;\\n            case '2':\\n              dateObj.description = 'Delivery Date';\\n              break;\\n            case '10':\\n              dateObj.description = 'Shipment Date';\\n              break;\\n            default:\\n              dateObj.description = 'Other Date';\\n          }\\n          \\n          result.dates.push(dateObj);\\n        }\\n        break;\\n      \\n      case 'NAD':\\n        // Name and Address\\n        // NAD+BY+CUSTOMER_123::91\\n        if (segments.length > 1) {\\n          const partyCode = segments[1];\\n          const partyId = segments[2]?.split(':')[0] || '';\\n          \\n          const party = {\\n            partyQualifier: partyCode,\\n            partyId: partyId,\\n            qualifierDescription: ''\\n          };\\n          \\n          // Add human-readable description\\n          switch (partyCode) {\\n            case 'BY':\\n              party.qualifierDescription = 'Buyer';\\n              break;\\n            case 'SU':\\n              party.qualifierDescription = 'Supplier';\\n              break;\\n            case 'DP':\\n              party.qualifierDescription = 'Delivery Party';\\n              break;\\n            default:\\n              party.qualifierDescription = 'Other Party';\\n          }\\n          \\n          // If there's a full name instead of a code (like \\\"Returns Processing Hub\\\")\\n          if (segments[2] && !segments[2].includes(':')) {\\n            party.partyName = segments[2];\\n            party.partyId = '';\\n          }\\n          \\n          result.parties.push(party);\\n        }\\n        break;\\n      \\n      case 'LIN':\\n        // Line Item\\n        // LIN+1++321654:IN\\n        currentLineItem = {\\n          lineNumber: segments[1],\\n          productId: '',\\n          productIdType: '',\\n          description: '',\\n          quantity: 0,\\n          unit: '',\\n          price: 0\\n        };\\n        \\n        // Parse product ID if present\\n        if (segments[3]) {\\n          const productParts = segments[3].split(':');\\n          currentLineItem.productId = productParts[0];\\n          currentLineItem.productIdType = productParts[1] || '';\\n        }\\n        \\n        result.lineItems.push(currentLineItem);\\n        break;\\n      \\n      case 'IMD':\\n        // Item Description\\n        // IMD+F++:::Defective Product A\\n        if (currentLineItem && segments.length > 3) {\\n          // The description is typically in the last component after multiple colons\\n          const descriptionParts = segments[3].split(':');\\n          currentLineItem.description = descriptionParts[descriptionParts.length - 1];\\n        }\\n        break;\\n      \\n      case 'QTY':\\n        // Quantity\\n        // QTY+21:10:EA\\n        if (currentLineItem && segments[1]) {\\n          const quantityParts = segments[1].split(':');\\n          currentLineItem.quantityQualifier = quantityParts[0];\\n          currentLineItem.quantity = parseFloat(quantityParts[1] || '0');\\n          currentLineItem.unit = quantityParts[2] || '';\\n        }\\n        break;\\n      \\n      case 'PRI':\\n        // Price Details\\n        // PRI+AAA:0.00\\n        if (currentLineItem && segments[1]) {\\n          const priceParts = segments[1].split(':');\\n          currentLineItem.priceQualifier = priceParts[0];\\n          currentLineItem.price = parseFloat(priceParts[1] || '0');\\n        }\\n        break;\\n      \\n      case 'UNT':\\n        // Message Trailer\\n        break;\\n      \\n      case 'UNZ':\\n        // Interchange Trailer\\n        break;\\n    }\\n  }\\n  \\n  // Add some summary info\\n  result.summary = {\\n    documentType: 'Return Order',\\n    documentNumber: result.orderDetails.documentNumber,\\n    orderDate: result.dates.find(d => d.qualifier === '137')?.date || '',\\n    lineItemCount: result.lineItems.length,\\n    totalQuantity: result.lineItems.reduce((sum, item) => sum + item.quantity, 0)\\n  };\\n  \\n  return result;\\n}\\n\\n// Return the parsed EDI data\\nconst ediMessage =  $input.first().json.body;\\n\\nif (!ediMessage) {\\n  throw new Error('No EDI message found in input. Please provide the EDI message in the \\\"ediMessage\\\" property.');\\n}\\n\\nconst parsedData = parseEDI(ediMessage);\\nreturn { json: parsedData };\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"0fa4b446-bb37-48ab-a44b-8b2c52e2660b\",\n      \"name\": \"Sticky Note4\",\n      \"type\": \"n8n-nodes-base.stickyNote\",\n      \"position\": [\n        -4100,\n        -1240\n      ],\n      \"parameters\": {\n        \"color\": 7,\n        \"width\": 700,\n        \"height\": 620,\n        \"content\": \"### 4. Store the Transactions in a Google Sheet\\nThis block will filter the order based on the order type (Return Orders, Outbound Orders) extracted from the order information node. Results are stored in two distinct sheets of the same Google Sheet file.\\n\\n#### How to setup?\\n- **Add Results in Google Sheets**:\\n   1. Add your Google Sheet API credentials to access the Google Sheet file\\n   2. Select the file using the list, an URL or an ID\\n   3. Select the sheet in which the vocabulary list is stored\\n   4. You don't need to create columns as the mapping is automatic.\\n  [Learn more about the Google Sheet Node]({{ $env.WEBHOOK_URL }}\"\n      },","sourceCodeStart":1314,"sourceCodeEnd":1350,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/workflows/Splitout/0793_Splitout_Code_Send_Triggered.json#L1314-L1350","documentation":"Thrown by 'Parse EDI Message' (workflow 0793). After parsing the EDIFACT message it reads const ediMessage = $input.first().json.body and throws this message when body is falsy. Note the mismatch: the message tells the user to supply an 'ediMessage' property, but the code actually reads .body — following the error text and providing ediMessage will not fix it.","triggerScenarios":"The webhook/gmail input delivers the raw EDI string under a different key — $json.message, $json.text, $json.payload, or (for Gmail triggers) a nested body structure — so json.body is undefined. An empty message body also triggers it.","commonSituations":"Webhook trigger posting the EDI as a form field or plain text body that n8n nests elsewhere; Gmail trigger where the EDI is in the email plain/html body requiring extraction first; switching the trigger type after the workflow was built; test executions with no sample data pinned.","solutions":["Run the trigger once and inspect the first item's json keys to find where the EDI string actually is.","Read the message with a fallback chain and fix the error text (see exampleFix).","If the source is Gmail, add an extract-text step before this node.","Pin a sample EDIFACT message so the parser can be tested standalone."],"exampleFix":"// before\nconst ediMessage = $input.first().json.body;\nif (!ediMessage) {\n  throw new Error('No EDI message found in input. Please provide the EDI message in the \"ediMessage\" property.');\n}\n\n// after\nconst j = $input.first().json;\nconst ediMessage = j.body ?? j.ediMessage ?? j.message ?? j.text;\nif (typeof ediMessage !== 'string' || !ediMessage.includes(\"'\")) {\n  throw new Error(`No EDI message found (looked in body/ediMessage/message/text; got keys: ${Object.keys(j).join(', ')})`);\n}","handlingStrategy":"validation","validationCode":"const j = $input.first().json;\nconst edi = [j.body, j.ediMessage, j.message, j.text].find(v => typeof v === 'string' && v.includes(\"'\"));\nif (!edi) throw new Error(`No EDI message (keys present: ${Object.keys(j).join(', ')})`);","typeGuard":"function isEdifactString(v) {\n  return typeof v === 'string' && /UNB\\+|UNH\\+|UNA/.test(v);\n}","tryCatchPattern":null,"preventionTips":["Make error messages name the property the code actually reads (body, not ediMessage).","Normalize the trigger payload in one dedicated Set/Code node right after the trigger.","Detect EDIFACT content (UNA/UNB/UNH segments) rather than just truthiness before parsing."],"tags":["n8n","edi","edifact","webhook","field-mapping"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}