/n8n-tutorials

How to fix “JSON parse error” after malformed model output in n8n?

Learn how to fix the "JSON parse error" in n8n caused by malformed AI model output by adding a Function node to detect, repair, and validate JSON for smooth workflow execution.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to fix “JSON parse error” after malformed model output in n8n?

To fix the "JSON parse error" in n8n that occurs after malformed model output, you need to add a Function node that can handle and repair the broken JSON. This typically happens when using AI models that sometimes produce incomplete or malformed JSON. You can implement error handling that detects and corrects the JSON structure before passing it to other nodes.

 

Understanding the JSON Parse Error in n8n

 

The "JSON parse error" in n8n typically occurs when a node receives data that it expects to be valid JSON, but the data is malformed. This is particularly common when working with AI model outputs like those from OpenAI, which might sometimes generate incomplete JSON responses.

When n8n tries to parse this malformed JSON, it throws an error and halts your workflow execution. This can be frustrating, especially when you're working with large language models that may occasionally produce imperfect outputs.

 

Step 1: Identify the Source of the Error

 

First, let's identify where the JSON parse error is occurring:

  1. Run your workflow in debug mode by clicking the "Execute Workflow" button.
  2. Look for the node that's throwing the "JSON parse error".
  3. Examine the input data to that node by viewing the output of the previous node.
  4. Identify the malformed JSON structure in the output.

Common issues include:

  • Incomplete JSON objects (missing closing braces or brackets)
  • Invalid escape sequences
  • Unquoted property names
  • Trailing commas
  • Missing quotes around string values

 

Step 2: Add a Function Node to Fix Malformed JSON

 

The most reliable solution is to add a Function node after the node that produces the potentially malformed JSON:

  1. Add a new Function node after the node that outputs the AI model response.
  2. Name it something descriptive like "Fix JSON".
  3. Add the following code to handle and repair common JSON issues:

// Function to fix malformed JSON
function fixMalformedJson(jsonString) {
  if (!jsonString || typeof jsonString !== 'string') {
    return null;
  }

  try {
    // First, try to parse as is
    return JSON.parse(jsonString);
  } catch (e) {
    // If parsing fails, attempt repairs
    console.log('JSON parse error. Attempting to fix malformed JSON:', e.message);
    
    let fixedJson = jsonString;
    
    // Fix 1: Balance braces and brackets
    const openBraces = (fixedJson.match(/{/g) || []).length;
    const closeBraces = (fixedJson.match(/}/g) || []).length;
    const openBrackets = (fixedJson.match(/[/g) || []).length;
    const closeBrackets = (fixedJson.match(/]/g) || []).length;
    
    // Add missing closing braces
    for (let i = 0; i < openBraces - closeBraces; i++) {
      fixedJson += '}';
    }
    
    // Add missing closing brackets
    for (let i = 0; i < openBrackets - closeBrackets; i++) {
      fixedJson += ']';
    }
    
    // Fix 2: Remove trailing commas
    fixedJson = fixedJson.replace(/,\s_}/g, '}').replace(/,\s_]/g, ']');
    
    // Fix 3: Try to fix unquoted property names
    fixedJson = fixedJson.replace(/(\w+):/g, '"$1":');
    
    try {
      return JSON.parse(fixedJson);
    } catch (e2) {
      console.log('Could not repair JSON:', e2.message);
      
      // If all else fails, return a default valid JSON object with the original text
      return {
        error: "Malformed JSON could not be repaired",
        originalText: jsonString,
        attemptedFix: fixedJson
      };
    }
  }
}

// Get the output from the previous node
const modelOutput = $input.item.json.output || $input.item.json.response || $input.item.json.content || $input.item.json;

let result;
// Handle different data types
if (typeof modelOutput === 'string') {
  // Try to fix and parse the JSON string
  result = fixMalformedJson(modelOutput);
} else if (typeof modelOutput === 'object') {
  // If it's already an object, no need to parse
  result = modelOutput;
} else {
  // Convert to string and try to fix
  result = fixMalformedJson(String(modelOutput));
}

// Return the fixed result
return {
  json: {
    fixedOutput: result
  }
};

 

Step 3: Handle Specific JSON Structure Issues

 

If your AI model outputs JSON with a specific structure that requires custom handling, modify the Function node code. For example, if you're working with OpenAI's API that outputs JSON in a specific format, you might need a more targeted approach:


// For OpenAI specific outputs
function extractJsonFromOpenAI(response) {
  try {
    // If it's already a valid JSON object
    if (typeof response === 'object') {
      return response;
    }
    
    // If it's a string containing JSON
    if (typeof response === 'string') {
      // Look for JSON object patterns
      const jsonMatch = response.match(/{[\s\S]\*}/);
      if (jsonMatch) {
        try {
          return JSON.parse(jsonMatch[0]);
        } catch (e) {
          // If direct parsing fails, try the general fix
          return fixMalformedJson(jsonMatch[0]);
        }
      }
      
      // Look for JSON array patterns
      const arrayMatch = response.match(/[[\s\S]\*]/);
      if (arrayMatch) {
        try {
          return JSON.parse(arrayMatch[0]);
        } catch (e) {
          // If direct parsing fails, try the general fix
          return fixMalformedJson(arrayMatch[0]);
        }
      }
    }
    
    // If no JSON structure is found, return a default object
    return {
      error: "No JSON structure found",
      originalText: response
    };
  } catch (e) {
    console.log('Error processing OpenAI response:', e.message);
    return {
      error: e.message,
      originalText: response
    };
  }
}

// Get the OpenAI response
const openAIResponse = $input.item.json.response || $input.item.json;

// Process and return the result
return {
  json: {
    fixedOutput: extractJsonFromOpenAI(openAIResponse)
  }
};

 

Step 4: Set Up JSON Validation

 

To ensure your fixed JSON conforms to a specific schema, add validation logic:


function validateJsonStructure(jsonObj, expectedSchema) {
  // Basic schema validation
  if (!jsonObj) {
    return false;
  }
  
  for (const requiredField of expectedSchema) {
    if (!(requiredField in jsonObj)) {
      return false;
    }
  }
  
  return true;
}

// Get the fixed JSON from previous steps
const fixedJson = $input.item.json.fixedOutput;

// Define your expected schema
const expectedSchema = ['name', 'age', 'email']; // Replace with your required fields

// Validate and handle accordingly
if (validateJsonStructure(fixedJson, expectedSchema)) {
  return {
    json: {
      valid: true,
      data: fixedJson
    }
  };
} else {
  // Create a default structure if validation fails
  return {
    json: {
      valid: false,
      data: {
        name: fixedJson.name || "Unknown",
        age: fixedJson.age || 0,
        email: fixedJson.email || "[email protected]"
      },
      originalData: fixedJson
    }
  };
}

 

Step 5: Configure Error Handling for the Workflow

 

Set up proper error handling in your n8n workflow:

  1. Add an Error Trigger node to handle errors that might still occur.
  2. Connect it to a Set node to format error messages.
  3. Optionally, add a notification node (like Send Email or Slack) to alert you of persistent issues.

// In the Set node connected to the Error Trigger
return {
  json: {
    error: true,
    message: `Workflow error: ${$input.item.json.error}`,
    nodeWithError: $input.item.json.node,
    timestamp: new Date().toISOString()
  }
};

 

Step 6: Implement Retry Logic

 

For more robust handling, implement a retry mechanism for model outputs:


// In a Function node
const maxRetries = 3;
const currentRetry = $input.item.json.retryCount || 0;

// If we haven't hit max retries and we have an error
if (currentRetry < maxRetries && $input.item.json.error) {
  return {
    json: {
      retryCount: currentRetry + 1,
      shouldRetry: true,
      lastError: $input.item.json.error
    }
  };
} else if (currentRetry >= maxRetries) {
  // We've hit max retries, give up and return an error
  return {
    json: {
      retryCount: currentRetry,
      shouldRetry: false,
      error: "Max retries exceeded. Could not fix JSON.",
      lastError: $input.item.json.error
    }
  };
} else {
  // No error or retry needed
  return $input.item;
}

 

Step 7: Test Your Solution

 

After implementing these fixes:

  1. Test with known malformed JSON samples to verify your repair logic works.
  2. Create test cases covering various types of JSON malformation.
  3. Run your workflow and verify that the JSON parse errors no longer occur.
  4. Check that downstream nodes are receiving correctly structured data.

 

Step 8: Create a Reusable Subworkflow

 

For reusability across multiple workflows:

  1. Select all nodes related to JSON fixing.
  2. Right-click and select "Create Subworkflow".
  3. Name it "JSON Error Handler".
  4. Configure input and output parameters.

This creates a reusable component you can add to any workflow where JSON parse errors might occur.

 

Step 9: Monitor and Improve

 

Set up ongoing monitoring to catch and improve JSON error handling:

  1. Add logging to track JSON errors (e.g., using the n8n Webhook node to send error data to a monitoring service).
  2. Analyze common error patterns to enhance your fix logic.
  3. Update your Function node code as you discover new types of malformations.

// In a Function node for logging
function logJsonError(error, input) {
  // You could send this to a logging service
  console.log('JSON Error Log:', {
    timestamp: new Date().toISOString(),
    error: error.message || error,
    inputSample: typeof input === 'string' ? input.substring(0, 100) + '...' : 'Non-string input',
    workflowId: $workflow.id,
    runId: $execution.id
  });
}

try {
  // Your JSON parsing code here
} catch (e) {
  logJsonError(e, $input.item.json);
  throw e; // Re-throw to trigger error handling
}

 

Step 10: Advanced Techniques for Complex Cases

 

For highly complex JSON structures or particularly problematic AI outputs, consider these advanced techniques:

  1. Use a more robust JSON repair library by installing a custom n8n module:
  • Create a custom n8n module with a package like "json-repair"
  • Import it in your Function node
  1. Implement a state machine approach for complex JSON parsing:

function advancedJsonRepair(input) {
  // Advanced state machine for JSON parsing
  const chars = input.split('');
  let result = '';
  let inString = false;
  let escapeNext = false;
  let bracketStack = [];
  let braceStack = [];
  
  for (let i = 0; i < chars.length; i++) {
    const char = chars[i];
    const nextChar = chars[i + 1] || '';
    
    // String handling logic
    if (char === '"' && !escapeNext) {
      inString = !inString;
    }
    
    // Escape character handling
    if (char === '\\' && !escapeNext) {
      escapeNext = true;
    } else {
      escapeNext = false;
    }
    
    // Track brackets and braces
    if (!inString) {
      if (char === '{') {
        braceStack.push(i);
      } else if (char === '}') {
        braceStack.pop();
      } else if (char === '[') {
        bracketStack.push(i);
      } else if (char === ']') {
        bracketStack.pop();
      }
      
      // Fix common issues
      if (char === ',' && (nextChar === '}' || nextChar === ']')) {
        continue; // Skip trailing commas
      }
    }
    
    result += char;
  }
  
  // Balance any remaining open brackets/braces
  while (braceStack.length > 0) {
    braceStack.pop();
    result += '}';
  }
  
  while (bracketStack.length > 0) {
    bracketStack.pop();
    result += ']';
  }
  
  return result;
}

// Get input and try to repair
const input = $input.item.json.output || '';
const repairedJson = advancedJsonRepair(input);

try {
  const parsedJson = JSON.parse(repairedJson);
  return { json: { fixedOutput: parsedJson, repaired: true } };
} catch (e) {
  return { 
    json: { 
      error: "Could not repair JSON even with advanced methods",
      attemptedFix: repairedJson,
      originalText: input 
    } 
  };
}

 

Conclusion

 

JSON parse errors are common when working with AI model outputs in n8n workflows. By implementing a robust error handling and repair strategy using Function nodes, you can create resilient workflows that handle malformed JSON gracefully. The key is to identify the specific types of JSON malformations you're encountering and implement targeted fixes.

For ongoing maintenance, continue to monitor and refine your JSON error handling logic as you encounter new edge cases. With proper implementation, your n8n workflows can become self-healing and more reliable when working with unpredictable AI model outputs.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022