Bug Description
Summary
The n8n structured output parser fails when AI agent responses contain markdown code blocks (triple backticks) inside JSON string values, causing workflow execution to fail with "Invalid JSON in model output" error.
Bug Details
Location
- File:
packages/@n8n/nodes-langchain/utils/output_parsers/N8nStructuredOutputParser.ts
- Line: 36
- Node:
format_final_json_response (Output Parser Structured node)
Error Message
NodeOperationError: Model output doesn't fit required format
Context: { outputParserFailReason: 'Invalid JSON in model output' }
Root Cause
The original parsing logic used a naive string splitting approach:
// BUGGY CODE
const jsonString = text.includes('```') ? text.split(/```(?:json)?/)[1] : text;
Problem: This code triggers on ANY occurrence of triple backticks (\```), including those inside JSON string values. When the AI response contains markdown with code blocks in the message field, it incorrectly splits at the first backtick occurrence, producing invalid JSON.
Example Failure Case
AI Agent Output (Valid JSON):
{
"output": {
"message": "## Example\n```bash\n--set globals.enable=false\n```\n",
"status": "completed"
}
}
Parser Behavior:
- Detects
``` inside the message string
- Splits at first
``` and takes second part
- Extracts:
bash\n--set globals.enable=false\n
- Attempts to parse as JSON → SyntaxError: Unexpected token 'b'
The Potential Fix
File: N8nStructuredOutputParser.ts (Lines 35-43)
// Extract JSON from markdown code fence if present
// Using regex to properly match code fences, even if backticks appear in the JSON content
let jsonString = text.trim();
// Look for a code fence with proper opening and closing
// Use GREEDY matching ([\s\S]+) to match to the LAST occurrence of closing ```
// This prevents matching backticks that appear inside JSON string values
// The pattern matches:
// - Opening: ``` or ```json followed by optional whitespace and optional newline
// - Content: Any characters (greedy - matches to last ```)
// - Closing: Optional newline, optional whitespace, then ```
// This handles both standard fences (with newlines) and inline fences (without)
const codeFenceMatch = jsonString.match(/```(?:json)?\s*\n?([\s\S]+)\n?\s*```/);
if (codeFenceMatch) {
// Extract the content between the fences
const potentialJson = codeFenceMatch[1].trim();
// Validate that what we extracted looks like JSON (starts with { or [)
// This helps avoid false positives from backticks inside JSON content
if (potentialJson.startsWith('{') || potentialJson.startsWith('[')) {
jsonString = potentialJson;
}
}
const json = JSON.parse(jsonString.trim());
How It Works
The regex pattern /```(?:json)?\s*\n?([\s\S]+)\n?\s*```/ ensures:
\``` - Matches the opening three backticks literally
(?:json)? - Non-capturing group that optionally matches the word "json"
\s* - Matches zero or more whitespace characters
\n? - Optionally matches a newline (handles both standard and inline fences)
([\s\S]+) - CAPTURE GROUP - The actual JSON content
[\s\S] = matches ANY character (whitespace OR non-whitespace)
+ = one or more times, GREEDY (matches to the LAST occurrence of closing ```)
\n? - Optionally matches newline before closing fence
\s* - Optional whitespace before closing backticks
\``` - Matches the closing three backticks
Key Points:
- Greedy matching ensures we match to the LAST occurrence of
```, not the first one inside JSON content
- Optional newlines (
\n?) handle both standard fences and inline fences (e.g., ```json\n{"foo":"bar"}```)
- Validation check provides extra safety by verifying extracted content starts with
{ or [
- No anchors allows text before/after the fence (e.g., "Here's the output:
json\n...\n")
To Reproduce
Provide in AI agent output message tripple backsticks and configure json shcema parser
Expected behavior
Parser passed for correct json.
Debug Info
Debug info
core
- n8nVersion: 1.116.2
- platform: docker (self-hosted)
- nodeJsVersion: 22.13.1
- nodeEnv: ci
- database: postgres
- executionMode: scaling (single-main)
- concurrency: -1
- license: enterprise (production)
storage
- success: all
- error: all
- progress: false
- manual: true
- binaryMode: memory
pruning
- enabled: true
- maxAge: 336 hours
- maxCount: 10000 executions
client
- userAgent: mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/141.0.0.0 safari/537.36
- isTouchDevice: false
security
Generated at: 2025-10-24T17:26:39.897Z
Operating System
node:22.13.1-bookworm-slim
n8n Version
1.116.2
Node.js Version
22.13.1
Database
PostgreSQL
Execution mode
queue
Hosting
self hosted
Bug Description
Summary
The n8n structured output parser fails when AI agent responses contain markdown code blocks (triple backticks) inside JSON string values, causing workflow execution to fail with "Invalid JSON in model output" error.
Bug Details
Location
packages/@n8n/nodes-langchain/utils/output_parsers/N8nStructuredOutputParser.tsformat_final_json_response(Output Parser Structured node)Error Message
Root Cause
The original parsing logic used a naive string splitting approach:
Problem: This code triggers on ANY occurrence of triple backticks (
\```), including those inside JSON string values. When the AI response contains markdown with code blocks in the message field, it incorrectly splits at the first backtick occurrence, producing invalid JSON.Example Failure Case
AI Agent Output (Valid JSON):
{ "output": { "message": "## Example\n```bash\n--set globals.enable=false\n```\n", "status": "completed" } }Parser Behavior:
```inside the message string```and takes second partbash\n--set globals.enable=false\nThe Potential Fix
File:
N8nStructuredOutputParser.ts(Lines 35-43)How It Works
The regex pattern
/```(?:json)?\s*\n?([\s\S]+)\n?\s*```/ensures:\``` - Matches the opening three backticks literally(?:json)?- Non-capturing group that optionally matches the word "json"\s*- Matches zero or more whitespace characters\n?- Optionally matches a newline (handles both standard and inline fences)([\s\S]+)- CAPTURE GROUP - The actual JSON content[\s\S]= matches ANY character (whitespace OR non-whitespace)+= one or more times, GREEDY (matches to the LAST occurrence of closing ```)\n?- Optionally matches newline before closing fence\s*- Optional whitespace before closing backticks\``` - Matches the closing three backticksKey Points:
```, not the first one inside JSON content\n?) handle both standard fences and inline fences (e.g.,```json\n{"foo":"bar"}```){or[json\n...\n")To Reproduce
Provide in AI agent output message tripple backsticks and configure json shcema parser
Expected behavior
Parser passed for correct json.
Debug Info
Debug info
core
storage
pruning
client
security
Generated at: 2025-10-24T17:26:39.897Z
Operating System
node:22.13.1-bookworm-slim
n8n Version
1.116.2
Node.js Version
22.13.1
Database
PostgreSQL
Execution mode
queue
Hosting
self hosted