Describe the problem/error/question
So my Problem is, im trying to build a part of my Workflow which goal it would be to: Get all unread emails → check my google sheet if the Emails arrived are already included in my google sheet list → if yes : Update existing Row // if no : Append a new Row.
I tried many different ways, tried to help myself with AI (gpt and gemini) also searched for workflows that are existing etc. No luck tho.
Please share your workflow
{
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"id": "3870938b-328c-46d6-8726-451d014a775b",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
-4992,
-96
]
},
{
"parameters": {
"url": "https://gmail.googleapis.com/gmail/v1/users/me/messages",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "gmailOAuth2",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "maxResults",
"value": "10"
}
]
},
"options": {}
},
"id": "88fca52f-4861-47e7-bbbd-156afcb384ea",
"name": "1. Get Unread Emails",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
-4544,
-256
],
"credentials": {
}
}
},
{
"parameters": {
"fieldToSplitOut": "messages",
"options": {}
},
"id": "af4b0276-c4d2-4a33-83dc-4bce9c944fcc",
"name": "2. Split Out Messages",
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
-4320,
-256
]
},
{
"parameters": {
"url": "=https://gmail.googleapis.com/gmail/v1/users/me/messages/{{$json[\"id\"]}}?format=full",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "gmailOAuth2",
"options": {}
},
"id": "f589e05c-94f5-4963-97a0-5907e2b57894",
"name": "3. Get Email Details",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
-4112,
-256
],
"credentials": {
}
}
},
{
"parameters": {
"assignments": {
"assignments": [
{
"name": "Email",
"type": "string",
"value": "={{ \n (() => {\n const headers = $('3. Get Email Details').item.json.payload.headers;\n const from = headers.find(h => h.name === 'From')?.value || '';\n const match = from.match(/<(.*?)>/);\n return match ? match[1].trim().toLowerCase() : 'Unbekannt';\n })()\n}}",
"id": "2a6f1842-c149-4c71-924e-fe1cdee873e3"
},
{
"name": "Name",
"type": "string",
"value": "={{ \n (() => {\n const headers = $('3. Get Email Details').item.json.payload.headers;\n const from = headers.find(h => h.name === 'From')?.value || '';\n return from.split('<')[0].trim();\n })()\n}}",
"id": "b0363fe5-d5bb-4805-9b4c-5b521ea9cf6a"
},
{
"name": "Betreff",
"type": "string",
"value": "={{ $node[\"3. Get Email Details\"].json.payload.headers.find(h => h.name.toLowerCase() === 'subject')?.value || '(Kein Betreff)' }}",
"id": "f4c8e61d-78e8-465b-b896-8495d7fca1ee"
},
{
"name": "Bemerkung",
"type": "string",
"value": "={{ $node[\"3. Get Email Details\"].json.snippet }}",
"id": "1a103afd-61bf-4d74-aef9-82a2676a06bc"
},
{
"name": "Eingang",
"type": "string",
"value": "={{ \n (() => { \n const headers = $('3. Get Email Details').item.json.payload.headers; \n const rawDate = headers.find(h => h.name === 'Date')?.value; \n if (!rawDate) return 'Kein Datum gefunden'; \n const parsed = new Date(rawDate); \n return parsed.toLocaleString('de-CH', { timeZone: 'Europe/Zurich' }); \n })()\n}}",
"id": "7ff4c2e3-c7d3-462e-a335-731ea93236aa"
}
]
},
"options": {}
},
"id": "7056d35b-9015-4952-9e13-ec11c7586713",
"name": "4. Extract Email Info",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-3888,
-256
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.row_number }}",
"operator": {
"type": "string",
"operation": "empty",
"singleValue": true
},
"id": "9e1fd617-e8b0-481d-bfca-c21c2e89bfa9"
}
],
"combinator": "and"
},
"looseTypeValidation": true,
"options": {}
},
"id": "54e9df75-a4de-4035-923a-5a88b4c5483e",
"name": "7. Email Exists?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
-3184,
-96
]
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_SHEET_ID_HERE",
"mode": "list"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Email": "={{ $json.Email }}",
"Name": "={{ $json.Name }}",
"Betreff": "={{ $json.Betreff }}",
"Bemerkung": "={{ $json.Bemerkung }}",
"Eingang": "={{ $json.Eingang }}",
"Prozessiert": false
}
},
"options": {}
},
"id": "673199c4-c183-47cc-a5de-5867679f0e92",
"name": "✅ Create New Row",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
-2816,
-512
],
"credentials": {
}
}
},
{
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "YOUR_SHEET_ID_HERE",
"mode": "list",
"cachedResultName": "Lead AI Test",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID_HERE/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "Tabellenblatt1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID_HERE/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Bemerkung": "={{ (() => {\n const current = $json[\"Bemerkung\"] || \"\";\n const from = $('4. Extract Email Info').item.json.from.value[0].address;\n const subject = $('4. Extract Email Info').item.json.subject;\n const body = $('4. Extract Email Info').item.json.text || \"⚠️ Kein Body gefunden\";\n const timestamp = new Date().toLocaleString(\"de-CH\");\n\n const newEntry = \n `\\n\\n=== 📩 Neues Gespräch am ${timestamp} ===\\n` +\n `---\\n📅 ${timestamp}\\n👤 ${from}\\n📝 ${subject}\\n\\n${body}\\n`;\n\n return newEntry + \"\\n\\n\" + current;\n})() }}",
"Betreff": "={{ $json.Betreff }}",
"Prozessiert": "FALSE",
"ThreadID": "={{ $json.Email }}",
"Follow-Up-State": "Pendent",
"Email": "={{ $('4. Extract Email Info').item.json.Email }}",
"row_number": "="
},
"matchingColumns": [
"Email"
],
"schema": [
{
"id": " Eingang",
"displayName": " Eingang",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Name",
"displayName": "Name",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Email",
"displayName": "Email",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Telefon",
"displayName": "Telefon",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Betreff",
"displayName": "Betreff",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Bemerkung",
"displayName": "Bemerkung",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Prozessiert",
"displayName": "Prozessiert",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "ThreadID",
"displayName": "ThreadID",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Follow-Up-State",
"displayName": "Follow-Up-State",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Follow-Up Date",
"displayName": "Follow-Up Date",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Termin Datum",
"displayName": "Termin Datum",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Termin Uhrzeit",
"displayName": "Termin Uhrzeit",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Reminder Sent",
"displayName": "Reminder Sent",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Agent Antwort",
"displayName": "Agent Antwort",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "row_number",
"displayName": "row_number",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"canBeUsedToMatch": true,
"readOnly": true,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"id": "5013f6db-06da-4fae-ae78-5e12a94fc18c",
"name": "🔄 Update Existing Row",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
-2784,
384
],
"credentials": {
}
}
},
{
"parameters": {
"jsCode": "// Input 1: The new emails (comes in as 'items')\n// Input 2: All the rows from your Google Sheet (we get this from the other node)\nconst sheetItems = $('5. Get All Sheet Rows').all();\n\n// Create a simple, fast lookup map of all the emails that already exist in the sheet.\n// We store the whole row, which is more powerful.\nconst sheetEmailMap = new Map(\n sheetItems.map(item => [item.json.Email.trim().toLowerCase(), item.json])\n);\n\n// This will be the final output of this node\nconst finalItems = [];\n\n// Loop through every new email\nfor (const item of items) {\n const incomingEmail = item.json.Email.trim().toLowerCase();\n \n // Look up the incoming email in our map of sheet emails\n const matchedSheetRow = sheetEmailMap.get(incomingEmail);\n\n if (matchedSheetRow) {\n // MATCH FOUND!\n // A row with this email already exists.\n // We will merge the sheet data (like 'row_number') into our item.\n // This tells the IF node that the item exists.\n Object.assign(item.json, matchedSheetRow);\n }\n\n // Add the item (now with sheet data, if it was found) to our results.\n finalItems.push(item);\n}\n\n// Return all the processed items.\nreturn finalItems;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-3424,
-96
],
"id": "aef8f1e0-185e-4563-9515-c4b27051c8ab",
"name": "Code in JavaScript"
},
{
"parameters": {
"documentId": {
"__rl": true,
"value": "YOUR_SHEET_ID_HERE",
"mode": "list",
"cachedResultName": "Lead AI Test",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID_HERE/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "Tabellenblatt1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID_HERE/edit#gid=0"
},
"options": {}
},
"id": "915e690e-88fb-4344-bf5c-607c54d3edae",
"name": "5. Get All Sheet Rows",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
-4112,
160
],
"executeOnce": true,
"alwaysOutputData": false,
"notesInFlow": false,
"retryOnFail": false,
"credentials": {
}
}
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "5. Get All Sheet Rows",
"type": "main",
"index": 0
},
{
"node": "1. Get Unread Emails",
"type": "main",
"index": 0
}
]
]
},
"1. Get Unread Emails": {
"main": [
[
{
"node": "2. Split Out Messages",
"type": "main",
"index": 0
}
]
]
},
"2. Split Out Messages": {
"main": [
[
{
"node": "3. Get Email Details",
"type": "main",
"index": 0
}
]
]
},
"3. Get Email Details": {
"main": [
[
{
"node": "4. Extract Email Info",
"type": "main",
"index": 0
}
]
]
},
"4. Extract Email Info": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"7. Email Exists?": {
"main": [
[
{
"node": "✅ Create New Row",
"type": "main",
"index": 0
}
],
[
{
"node": "🔄 Update Existing Row",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "7. Email Exists?",
"type": "main",
"index": 0
}
]
]
},
"5. Get All Sheet Rows": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": ""
}
}
Share the output returned by the last node
Cannot assign to read only property ‘name’ of object ‘Error: Node ‘5. Get All Sheet Rows’ hasn’t been executed’
So this error happens just since i updated my workflow in general with a custom code node.
This would have been my solution since with the merge node i was not able to fix the workflow.
But now it wont execute my Get sheet Row’s when executing the trigger(workflow trigger) When i do it manually it works tho. I tried every debugging method the assistant gave me.
But im Open to any solution that will work, important is just that it would work, the workflow itself can be changed.
Im happy for any Input / Help. Thank you also this is my first Post, so if i miss any infos or anything just let me know
BG
neuBau
Information on your n8n setup
- n8n version: [email protected]
- Running n8n via n8n cloud
- Operating system: windows 10