Skip to main content

Hello Airtable Community.  

I've reached my wits end and so has chatGPT 🙂  I am using the following scripting code in an Automation to extract some data from the record that triggered the automation and insert into an external API.  Most of it is working as expected until the very end of the first function where I keep getting 

 

 

CONSOLE.ERROR "Error processing Airtable update:" "Unexpected end of JSON input"

 

 

I've tried lots of logs to understand the input and everything appears in order to me.  JSON is coming back fine in each of the "console.logs" indicated in the code here.  An example here:

What could be causing this error?  Source code below:

 

 

// Function to escape HTML characters function escapeHtml(input) { return input.replace(/</g, "&lt;").replace(/>/g, "&gt;"); } // Airtable Script to trigger on "Terpene Tags" field update // Airtable Base ID and Table Name const AIRTABLE_BASE_ID = 'XXX'; const AIRTABLE_TABLE_NAME = 'XXX'; // Personal Access Token for Airtable const AIRTABLE_PERSONAL_ACCESS_TOKEN = 'XXX'; // External API endpoint const EXTERNAL_API_ENDPOINT = 'https://api.pos.dutchie.com/package/add-tags'; const EXTERNAL_API_KEY = 'XXX'; // Replace with your actual API key // Relevant roomIds const RELEVANT_ROOM_IDS = ['10650', '6454']; // Airtable Script function to handle updates async function onTerpeneTagsUpdate(event) { try { const recordId = event ? event.recordId : undefined; console.log('Record Id:', recordId); if (!recordId) { console.error('RecordId is missing. Exiting script.'); return; } // Fetch data from Airtable const airtableRecord = await fetchAirtableRecord(recordId); console.log('Airtable Record:', airtableRecord); // Check if 'fields' property exists before accessing it if (airtableRecord && airtableRecord.fields) { // Access 'fields' property safely console.log(airtableRecord.fields); // Now you can access specific properties of 'fields' const productName = airtableRecord.fields["ProductIdNumber"]; const productTagsString = airtableRecord.fields["Terpene Names"]; console.log("productName:", productName); console.log("productTags:", productTagsString); // Convert the comma-separated string to an array const productTags = productTagsString.split(',').map(tag => tag.trim()); console.log("Terpene Tags As Array:", productTags); // Add more processing logic as needed } else { // Handle the case where 'fields' is undefined console.error("Error: 'fields' property is undefined"); // You might want to handle this error appropriately, depending on your use case return; // Exit the function if 'fields' is undefined } if (!airtableRecord || !airtableRecord.fields) { console.error('Airtable record not found or has missing fields. Exiting script.'); return; } // Use the new numeric field for productId const productId = airtableRecord.fields.ProductIdNumber; // Fetch data from /inventory endpoint const inventoryData = await fetchInventoryData(); console.log("Inventory Data:", inventoryData); // Filter relevant packages (considering roomId for sale) const relevantPackages = inventoryData.filter( (package) => package.fields.productId === productId && RELEVANT_ROOM_IDS.includes(package.fields.roomId) ); // Build payload const payload = { packageIds: relevantPackages.map((p) => p.fields.packageId), tags: airtableRecord.fields['Terpene Names'], // Assuming you have the "Terpene Names" field }; // Make API call to external endpoint await makeExternalAPICall(payload); console.log('Tags added successfully'); } catch (error) { console.error('Error processing Airtable update:', error.message); } } let parsedData; // Declare parsedData at a higher scope // Function to safely parse JSON function parseJSONSafe(jsonString) { try { return JSON.parse(jsonString); } catch (error) { console.error("Error parsing JSON:", error); return null; } } // Updated fetchAirtableRecord function async function fetchAirtableRecord(recordId) { const response = await fetch( `https://api.airtable.com/v0/${AIRTABLE_BASE_ID}/${AIRTABLE_TABLE_NAME}/${recordId}`, { method: 'GET', headers: { Authorization: `Bearer ${AIRTABLE_PERSONAL_ACCESS_TOKEN}`, }, } ); console.log('Airtable API Response:', response.status, response.statusText); console.log('Airtable API Headers:', response.headers); if (!response.ok) { console.error(`Failed to fetch Airtable record: ${response.status} - ${response.statusText}`); return null; } const responseBody = await response.text(); console.log("Airtable Response Body:", responseBody); // Safely parse the JSON const parsedData = parseJSONSafe(responseBody); if (!parsedData || !parsedData.fields) { console.error("Error: Invalid Airtable record structure"); return null; } // Access the correct key for the record ID const id = parsedData.id; console.log("Record ID:", id); // Now you can use the "id" as needed // Return the parsed data return parsedData; } // Function to fetch data from /inventory endpoint async function fetchInventoryData() { const response = await fetch('https://api.pos.dutchie.com/inventory'); const data = await response.json(); return data.records; } // Function to make API call to external endpoint async function makeExternalAPICall(payload) { const response = await fetch(EXTERNAL_API_ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'application/json-patch+json', 'Authorization': `Bearer ${EXTERNAL_API_KEY}`, // Include your API key here }, body: JSON.stringify(payload), }); if (!response.ok) { throw new Error(`Failed to make external API call: ${response.status} - ${response.statusText}`); } } // Example: Trigger this function when Airtable record is updated const event = input.config(); // Use input.config() to get the input data from the automation onTerpeneTagsUpdate(event);

 

 

Any ideas?

Be the first to reply!