Response to HTTP Post not passing to function

I have this flow which is looking at a HomeAssistant calendar to get some events, find the location, and determine if it's a valid location to navigate to based on a call to an API service. I'm able to make the call and get successful JSON object responses, but the payload is not heading to the subsequent "Process API Response" node.

I'm unsure as to why the payload isn't making it to the function node for processing.

[{"id":"e98a2845c94d19d3","type":"group","z":"5061f200ee03cc5b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["7b71bdad4d104907","05810d1be569a7df","19f7c1e0f7d1b556","2fc0875ea0489ad7","679827f1aa43ba5b","a62c2c516b0baa2b","d87ac9981f4b4d0e","ee79af4b43b81306","2c0af32661e0dc62"],"x":14,"y":419,"w":1732,"h":322},{"id":"7b71bdad4d104907","type":"inject","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Trigger","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":110,"y":460,"wires":[["a62c2c516b0baa2b"]]},{"id":"05810d1be569a7df","type":"function","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Prepare Address Validation Request","func":"let unvalidatedEvents = msg.payload;  // All unvalidated events\nlet requests = [];\n\n// Iterate through unvalidated events and create a proper request format\nunvalidatedEvents.forEach(event => {\n    let location = event.event.location;\n    \n    // Prepare the address validation request using the full location\n    let addressValidationRequest = {\n        address: {\n            \"addressLines\": [location.fullAddress || JSON.stringify(location)]\n        }\n    };\n\n    // Clone the original message object and set the payload to the address validation request\n    let newMsg = { ...msg };\n    newMsg.payload = addressValidationRequest;\n\n    // Add the new message to the requests array\n    requests.push(newMsg);\n});\n\n// Check if there are any requests to send\nif (requests.length > 0) {\n    // Return the array of messages for the next node in the flow\n    return [requests];\n} else {\n    // If no unvalidated events, return null\n    return null;\n}\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":970,"y":460,"wires":[["679827f1aa43ba5b","d87ac9981f4b4d0e"]]},{"id":"19f7c1e0f7d1b556","type":"function","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Process API Response","func":"let responses = msg.payload; // API responses\nlet events = global.get('events') || [];\n\nconsole.log('Received responses:', responses);\nconsole.log('Current events:', events);\n\n// Iterate over the responses and check the verdict criteria\nresponses.forEach((response, index) => {\n    let event = events[index];\n\n    console.log('Processing response for event:', event);\n\n    if (response.result && response.result.verdict) {\n        let verdict = response.result.verdict;\n\n        console.log('Verdict:', verdict);\n\n        // Check for the presence of verdict fields and handle missing ones\n        let validationGranularity = verdict.validationGranularity || \"UNKNOWN\";\n        let hasUnconfirmedComponents = verdict.hasUnconfirmedComponents || false;\n        let hasInferredComponents = verdict.hasInferredComponents || false;\n        let hasReplacedComponents = verdict.hasReplacedComponents || false;\n        let addressComplete = verdict.addressComplete || false; // Defaulting to false if missing\n\n        console.log('Validation granularity:', validationGranularity);\n        console.log('Has unconfirmed components:', hasUnconfirmedComponents);\n        console.log('Has inferred components:', hasInferredComponents);\n        console.log('Has replaced components:', hasReplacedComponents);\n        console.log('Address complete:', addressComplete);\n\n        // Check if all the required conditions are met\n        if (\n            validationGranularity === \"PREMISE\" &&\n            addressComplete === true &&\n            hasUnconfirmedComponents === false &&\n            hasInferredComponents === false &&\n            hasReplacedComponents === false\n        ) {\n            // Mark event as validated and valid\n            event.event.validated = true;\n            event.event.addressValid = true;\n            console.log('Event marked as validated and valid');\n        } else {\n            // Mark event as validated but invalid\n            event.event.validated = true;\n            event.event.addressValid = false;\n            console.log('Event marked as validated but invalid');\n        }\n    } else {\n        // If there's no verdict or result, mark as invalid\n        event.event.validated = true;\n        event.event.addressValid = false;\n        console.log('Event marked as invalid');\n    }\n});\n\n// Save the updated events back to global context\nglobal.set('events', events);\nconsole.log('Updated events:', events);\n\nmsg.payload = events; // Return the updated events in payload\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1620,"y":600,"wires":[["2c0af32661e0dc62"]]},{"id":"2fc0875ea0489ad7","type":"debug","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Filter Unvalidated Events","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":310,"y":560,"wires":[]},{"id":"679827f1aa43ba5b","type":"http request","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Post to Google Address Validation Service","method":"POST","ret":"obj","paytoqs":"body","url":"http://validation-server:8080/validate-address","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[{"keyType":"other","keyValue":"x-api-key","valueType":"other","valueValue":"x"},{"keyType":"other","keyValue":"Content-Type","valueType":"other","valueValue":"application/json"}],"x":1340,"y":460,"wires":[["ee79af4b43b81306","19f7c1e0f7d1b556"]]},{"id":"a62c2c516b0baa2b","type":"function","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Filter Unvalidated Events","func":"let events = global.get('events') || [];\nlet unvalidatedEvents = [];\n\n// Filter events with validated set to false\nfor (let event of events) {\n    if (!event.event.validated) {\n        unvalidatedEvents.push(event);\n    }\n}\n\nmsg.payload = unvalidatedEvents;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":460,"wires":[["2fc0875ea0489ad7","05810d1be569a7df"]]},{"id":"d87ac9981f4b4d0e","type":"debug","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Prepare Address Validation Request","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":540,"wires":[]},{"id":"ee79af4b43b81306","type":"debug","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Post to Google Address Validation Service","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1020,"y":640,"wires":[]},{"id":"2c0af32661e0dc62","type":"debug","z":"5061f200ee03cc5b","g":"e98a2845c94d19d3","name":"Process API Response","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1220,"y":700,"wires":[]}]

What do you see in the Post to Google debug output? Whatever you see there will certainly be getting to the function node.

Here's a sample output from the debug node set to the complete message object:

10/17/2024, 8:16:01 PM[node: Post to Google Address Validation Service]

(http://noderedserver:1880/#)msg : Object

object

_msgid: "64cbdcaa1de71f7c"

payload: object

responseId: "e8b162be-8455-4120-968c-e4da781ead71"

result: object

address: object

addressComponents: array[7]

formattedAddress: "123 Main Street, White Plains, NY 10601-3104, USA"

missingComponentTypes: array[1]

0: "subpremise"

postalAddress: object

addressLines: array[1]

0: "123 Main St"

administrativeArea: "NY"

languageCode: "en"

locality: "White Plains"

postalCode: "10601-3104"

regionCode: "US"

geocode: object

metadata: object

uspsData: object

verdict: object

topic: ""

statusCode: 200

headers: object

server: "gunicorn"

date: "Fri, 18 Oct 2024 00:16:00 GMT"

connection: "close"

content-type: "application/json"

content-length: "2448"

x-node-red-request-node: "ddddc684"

responseUrl: "http://address-validation-service:8080/validate-address"

redirectList: array[0]

retry: 0
z

In the function you have

let responses = msg.payload; // API responses
let events = global.get('events') || [];

console.log('Received responses:', responses);
console.log('Current events:', events);

// Iterate over the responses and check the verdict criteria
responses.forEach((response, index) => {

which expects msg.payload to be an array. But, as you can see from the debug output:

msg.payload is an object not an array.

In future, if posting debug output, please use the Copy Value popup in the debug pane, which will generate a JSON string value which can be pasted directly into an Inject node for testing flows. This canned text explains how to get the value:

There’s a great page in the docs (Working with messages : Node-RED) that will explain how to use the debug panel to find the right path/value for any data item.

Pay particular attention to the part about the buttons that appear under your mouse pointer when you over hover a debug message property in the sidebar.

BX00Cy7yHi

Understood -- I wanted to copy the entire debug payload in this case (including the HTTP code response) to provide context, but I'll make sure to do just the JSON next time.

Beyond that, this appears to be parsing correctly (although it has uncovered another challenge, but that's another thread). Thanks for the help!!