Using Code Node to translate webb app inputs to google sheet data

Hi there, I’m new to N8N so please explain things like I’m a 5 year old :slight_smile:

Problem: I created a webb app to take in the following information:
date (calendar picker)
meal type (buttons for breakfast/lunch/dinner/etc)
Free text input for what I ate {e.g. 2 eggs)

The workflow is pulling the input correctly in from the web app, but my OpenAI node is hallucinating the data and outputting completely different info that I have put in. Can anyone guide me on how to correct this please?

Example input:
2025-06-25
Breakfast
2 eggs

Example Output: (the Open AI node just making stuff up)
2021-01-21
Dinner
Omelette with cheese and spinach

My workflow:

{
“nodes”: [
{
“parameters”: {
“modelId”: {
“__rl”: true,
“value”: “gpt-4”,
“mode”: “id”
},
“messages”: {
“values”: [
{
“content”: “You are a nutrition macro calculator. Given a natural-language meal description, return only the following in JSON format:\n\n{\n "date": "{{$json["date"]}}",\n "meal": "{{$json["meal_type"]}}",\n "description": "{{$json["meal_description"]}}"\n "calories": 0,\n "protein_g": 0,\n "carbs_g": 0,\n "sugar_g": 0,\n "fat_g": 0,\n "fiber_g": 0\n}\n\nRules:\n- Estimate macros based on known macros for that specific item\n- Use all lowercase field names exactly.\n- Do NOT explain anything. Respond ONLY with valid JSON. No text, no notes, no formatting.\n- for the "date", "meal type" and "meal description" fields, copy the exact information provided in the input, do not change it in any way. Do not change the date, do not change the meal type, do not embellish. \n”
}
]
},
“options”: {}
},
“type”: “@n8n/n8n-nodes-langchain.openAi”,
“typeVersion”: 1.8,
“position”: [
220,
0
],
“id”: “2205d1d9-ecde-4d76-8d11-26d4922f6f65”,
“name”: “Message a model”,
“credentials”: {
“openAiApi”: {
“id”: “42E9DC3hajkws1jH”,
“name”: “OpenAi account”
}
}
},
{
“parameters”: {
“operation”: “append”,
“documentId”: {
“__rl”: true,
“value”: “1WgGtjLX-471I2SsRY8dZFo9q03-1T-7kmNDpgDgyZtQ”,
“mode”: “list”,
“cachedResultName”: “Macro Product Library”,
“cachedResultUrl”: “https://docs.google.com/spreadsheets/d/1WgGtjLX-471I2SsRY8dZFo9q03-1T-7kmNDpgDgyZtQ/edit?usp=drivesdk
},
“sheetName”: {
“__rl”: true,
“value”: 1176809213,
“mode”: “list”,
“cachedResultName”: “Meal Log”,
“cachedResultUrl”: “https://docs.google.com/spreadsheets/d/1WgGtjLX-471I2SsRY8dZFo9q03-1T-7kmNDpgDgyZtQ/edit#gid=1176809213
},
“columns”: {
“mappingMode”: “defineBelow”,
“value”: {
“protein_g”: “={{ $json.protein_g }}”,
“calories”: “={{ $json.calories }}”,
“carbs_g”: “={{ $json.carbs_g }}”,
“sugar_g”: “={{ $json.sugar_g }}”,
“fat_g”: “={{ $json.fat_g }}”,
“fiber_g”: “={{ $json.fiber_g }}”,
“meal”: “={{ $json.meal }}”,
“date”: “={{ $json.date }}”,
“meal_description”: “{{ $json["meal_description"] || $items("Webhook1", 0).json.body.meal_description }}”
},
“matchingColumns”: ,
“schema”: [
{
“id”: “date”,
“displayName”: “date”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “meal”,
“displayName”: “meal”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “calories”,
“displayName”: “calories”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “protein_g”,
“displayName”: “protein_g”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “carbs_g”,
“displayName”: “carbs_g”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “sugar_g”,
“displayName”: “sugar_g”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “fat_g”,
“displayName”: “fat_g”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “fiber_g”,
“displayName”: “fiber_g”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
},
{
“id”: “meal_description”,
“displayName”: “meal_description”,
“required”: false,
“defaultMatch”: false,
“display”: true,
“type”: “string”,
“canBeUsedToMatch”: true,
“removed”: false
}
],
“attemptToConvertTypes”: false,
“convertFieldsToString”: false
},
“options”: {}
},
“type”: “n8n-nodes-base.googleSheets”,
“typeVersion”: 4.6,
“position”: [
780,
0
],
“id”: “462a2f62-43c4-4fa7-8155-38f9fd553290”,
“name”: “Append row in sheet”,
“credentials”: {
“googleSheetsOAuth2Api”: {
“id”: “nTynySsX1sxlVewf”,
“name”: “Google Sheets account”
}
}
},
{
“parameters”: {
“jsCode”: “const raw = $json.message.content;\nconst parsed = JSON.parse(raw);\n\nreturn [{\n json: {\n …$json.body, // preserves Lovable form input\n …parsed // adds GPT-calculated macros\n }\n}];\n”
},
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
580,
0
],
“id”: “47a86c33-cd78-45b6-afaa-c0a285e3c2aa”,
“name”: “Code”
},
{
“parameters”: {
“httpMethod”: “POST”,
“path”: “log-meal”,
“options”: {}
},
“type”: “n8n-nodes-base.webhook”,
“typeVersion”: 2,
“position”: [
-40,
0
],
“id”: “89002ff0-e202-44b3-b6bd-8d980bd6ff5f”,
“name”: “Webhook1”,
“webhookId”: “5cb636d3-f81b-4a4e-ab21-171b30eccbb7”
}
],
“connections”: {
“Message a model”: {
“main”: [
[
{
“node”: “Code”,
“type”: “main”,
“index”: 0
}
]
]
},
“Append row in sheet”: {
“main”: [

]
},
“Code”: {
“main”: [
[
{
“node”: “Append row in sheet”,
“type”: “main”,
“index”: 0
}
]
]
},
“Webhook1”: {
“main”: [
[
{
“node”: “Message a model”,
“type”: “main”,
“index”: 0
}
]
]
}
},
“pinData”: {},
“meta”: {
“templateCredsSetupCompleted”: true,
“instanceId”: “02e9e6356e51fca4e885ed93e1e16f8158e3605b3bb1e0f882efa0899cb5d143”
}
}

Use {{ $json.body.date }} (instead of just $json["date"])

In your OpenAI node prompt, you’re doing this:
“date”: “{{$json[“date”]}}”,
“meal”: “{{$json[“meal_type”]}}”,
“description”: “{{$json[“meal_description”]}}”

:white_check_mark: Fix the prompt to this:
“date”: “{{$json[“body”][“date”]}}”,
“meal”: “{{$json[“body”][“meal_type”]}}”,
“description”: “{{$json[“body”][“meal_description”]}}”

OR

you can just simply add a set node right after the Webhook*, and inside it map:

{
“date”: “2025-06-25”,
“meal_type”: “Breakfast”,
“meal_description”: “2 eggs”
}

This helps OpenAI read it properly without guessing.

Hope this helps mate!