Structure fallback messages in n8n when a language model fails by enabling Continue On Fail on the LLM node, adding an IF node to detect errors, and routing to a fallback path that returns a friendly message or calls a backup model. This pattern ensures your chatbot or API always responds gracefully instead of showing raw error messages to users.
Why Structure Fallback Messages for AI Model Failures
Language model APIs fail for many reasons: rate limits, timeouts, outages, context length exceeded, or invalid responses. When your n8n workflow powers a chatbot or customer-facing API, a raw error message like '429 Too Many Requests' provides a terrible user experience. Fallback messages let you intercept these errors and return something useful instead — a polite apology, a cached response, or output from a backup model. This pattern is essential for any production AI workflow that serves end users.
Prerequisites
- A running n8n instance with a workflow that calls a language model (OpenAI, Claude, etc.)
- Basic familiarity with the IF node and Respond to Webhook node
- Understanding of how n8n error handling works (Continue On Fail setting)
- A webhook-triggered workflow or chatbot workflow that needs graceful error handling
Step-by-step guide
Enable Continue On Fail on the LLM node
Enable Continue On Fail on the LLM node
By default, when a node fails, n8n stops the entire workflow. To handle errors gracefully, you need the workflow to continue running after a failure. Open your language model node (OpenAI, HTTP Request to Claude, etc.), go to the Settings tab, and enable Continue On Fail. When enabled, the node passes error information to the next node instead of stopping the workflow. The error data includes the error message and a flag indicating failure.
1// When Continue On Fail is enabled, a failed node outputs:2// {3// "json": {4// "error": {5// "message": "429 Too Many Requests",6// "description": "Rate limit exceeded. Please retry after 60 seconds."7// }8// }9// }10//11// A successful node outputs normal data:12// {13// "json": {14// "choices": [{"message": {"content": "Hello! How can I help?"}}]15// }16// }Expected result: The LLM node no longer stops the workflow on failure. Instead, it passes error data to the next connected node.
Add an IF node to detect errors
Add an IF node to detect errors
After the LLM node, add an IF node to check whether the response is an error or a success. Check for the presence of an error field in the output. If the error field exists, route to the fallback path. If it does not exist, continue with normal processing. This creates a fork in your workflow: one path for successful responses and one for error handling.
1// IF node configuration2// Condition: Check if the response contains an error3//4// Value 1: {{ $json.error }}5// Operation: is not empty6//7// True branch → Fallback message path (error occurred)8// False branch → Normal processing path (success)Expected result: The IF node routes failed LLM responses to the True branch and successful responses to the False branch.
Create a friendly fallback response
Create a friendly fallback response
On the True (error) branch of the IF node, add a Set node or Respond to Webhook node that returns a user-friendly message. The fallback message should acknowledge the issue without exposing technical details. Include a polite apology and a suggestion to try again. If your workflow uses Respond to Webhook, return the fallback message as the HTTP response so the user sees a friendly message instead of an error.
1// Set node on the error branch — create a friendly fallback2// Field: response3// Value:45I'm sorry, I'm unable to process your request right now. Please try again in a moment. If the issue persists, our team has been notified and is looking into it.67// Or use a Code node for more control:8const errorMessage = $json.error?.message || 'Unknown error';910let fallbackResponse;11if (errorMessage.includes('429') || errorMessage.includes('rate limit')) {12 fallbackResponse = 'I\'m receiving a lot of requests right now. Please try again in about 30 seconds.';13} else if (errorMessage.includes('timeout')) {14 fallbackResponse = 'My response took too long to generate. Please try a shorter question.';15} else {16 fallbackResponse = 'I\'m temporarily unable to respond. Please try again shortly.';17}1819return [{20 json: {21 response: fallbackResponse,22 isError: true,23 errorType: errorMessage24 }25}];Expected result: When the LLM fails, the user receives a friendly, context-appropriate fallback message instead of a raw error.
Route to a backup model
Route to a backup model
For higher reliability, route errors to a backup language model instead of a static message. On the error branch, add a second LLM node configured with a different provider or model. For example, if your primary model is GPT-4, use GPT-3.5-turbo as a backup. If your primary is Claude, fall back to OpenAI. This ensures the user still gets an AI-generated response even when the primary model is unavailable.
1// Backup model pattern:2// Primary: OpenAI GPT-4 → IF (error check) → True: Backup Model3// → False: Normal response45// Backup Code node to prepare the prompt for the fallback model:6const originalPrompt = $('Webhook').first().json.body.message;78return [{9 json: {10 prompt: originalPrompt,11 model: 'gpt-3.5-turbo',12 systemMessage: 'You are a helpful assistant. The user\'s question may have been intended for a more capable model. Do your best to provide a useful response.'13 }14}];1516// Connect this to a second OpenAI node configured with GPT-3.5-turbo17// Add another IF node after the backup model in case it also failsExpected result: When the primary model fails, the backup model processes the same prompt. Users receive an AI-generated response from the fallback model.
Log errors for monitoring
Log errors for monitoring
While the user sees a friendly message, you should still log the error for debugging. Add a parallel branch from the IF node's True output that sends the error details to a logging destination: a Slack channel, an email, a database, or a log file. This way you know when and why models are failing without affecting the user experience. Include the error message, timestamp, user input, and workflow execution ID.
1// Code node: Prepare error log entry (connect in parallel to fallback)2const errorData = $json.error || {};3const userInput = $('Webhook').first().json.body?.message || 'unknown';45return [{6 json: {7 level: 'error',8 source: 'llm-fallback',9 message: errorData.message || 'Unknown LLM error',10 userInput: userInput.substring(0, 200),11 timestamp: new Date().toISOString(),12 executionId: $execution.id,13 workflowName: $workflow.name14 }15}];1617// Connect this to:18// - Slack node (post to #errors channel)19// - Send Email node (alert the team)20// - PostgreSQL node (insert into error_logs table)Expected result: Every LLM failure is logged with context while the user receives the fallback message. Your team can monitor failure rates and patterns.
Complete working example
1{2 "name": "Chatbot with LLM Fallback",3 "nodes": [4 {5 "parameters": { "httpMethod": "POST", "path": "chat", "responseMode": "responseNode" },6 "name": "Webhook",7 "type": "n8n-nodes-base.webhook",8 "typeVersion": 1,9 "position": [250, 300]10 },11 {12 "parameters": {13 "url": "https://api.openai.com/v1/chat/completions",14 "method": "POST",15 "authentication": "predefinedCredentialType",16 "jsonBody": "={{ JSON.stringify({ model: 'gpt-4', messages: [{ role: 'user', content: $json.body.message }], max_tokens: 500 }) }}"17 },18 "name": "Primary LLM",19 "type": "n8n-nodes-base.httpRequest",20 "typeVersion": 4,21 "position": [470, 300],22 "continueOnFail": true23 },24 {25 "parameters": {26 "conditions": { "string": [{ "value1": "={{ $json.error }}", "operation": "isNotEmpty" }] }27 },28 "name": "Check Error",29 "type": "n8n-nodes-base.if",30 "typeVersion": 1,31 "position": [690, 300]32 },33 {34 "parameters": {35 "jsCode": "const errMsg = $json.error?.message || '';\nlet fallback;\nif (errMsg.includes('429')) { fallback = 'I am receiving many requests. Please try again in 30 seconds.'; }\nelse if (errMsg.includes('timeout')) { fallback = 'The response took too long. Please try a shorter question.'; }\nelse { fallback = 'I am temporarily unable to respond. Please try again shortly.'; }\nreturn [{ json: { response: fallback } }];"36 },37 "name": "Fallback Message",38 "type": "n8n-nodes-base.code",39 "typeVersion": 2,40 "position": [910, 400]41 },42 {43 "parameters": {44 "respondWith": "json",45 "responseBody": "={{ JSON.stringify({ reply: $json.choices ? $json.choices[0].message.content : $json.response }) }}"46 },47 "name": "Respond",48 "type": "n8n-nodes-base.respondToWebhook",49 "typeVersion": 1,50 "position": [1130, 300]51 }52 ],53 "connections": {54 "Webhook": { "main": [[{ "node": "Primary LLM", "type": "main", "index": 0 }]] },55 "Primary LLM": { "main": [[{ "node": "Check Error", "type": "main", "index": 0 }]] },56 "Check Error": { "main": [57 [{ "node": "Fallback Message", "type": "main", "index": 0 }],58 [{ "node": "Respond", "type": "main", "index": 0 }]59 ]},60 "Fallback Message": { "main": [[{ "node": "Respond", "type": "main", "index": 0 }]] }61 }62}Common mistakes when structuring Fallback Messages if a Model Fails in n8n
Why it's a problem: Forgetting to enable Continue On Fail, causing the entire workflow to stop on LLM errors
How to avoid: Open the LLM node, go to the Settings tab, and toggle Continue On Fail to enabled.
Why it's a problem: Exposing raw error messages to end users
How to avoid: Always intercept errors with an IF node and replace them with user-friendly messages before responding.
Why it's a problem: Not testing the fallback path during development
How to avoid: Temporarily use invalid API credentials or a wrong endpoint URL to trigger the error path and verify your fallback logic works.
Why it's a problem: Using the same provider for both primary and backup models
How to avoid: If the provider is down, both models fail. Use different providers (e.g., OpenAI primary, Anthropic backup) for true redundancy.
Best practices
- Always enable Continue On Fail on nodes that call external APIs or language models
- Write fallback messages that are friendly and context-aware based on the error type
- Use a backup model from a different provider to maximize availability
- Log all errors to a monitoring channel while serving fallback responses to users
- Include rate-limit-specific messages that tell users to wait and try again
- Test your fallback paths by temporarily breaking the API credentials
- Keep fallback messages short and actionable — tell the user what to do next
- Add a second fallback layer in case the backup model also fails
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
My n8n chatbot workflow calls OpenAI but sometimes gets rate limited or times out. How do I add fallback logic so users always get a friendly response even when the AI model fails?
Help me build an n8n workflow with a primary OpenAI node that falls back to a Claude node when OpenAI returns an error, and shows a static message if both fail.
Frequently asked questions
What does Continue On Fail do in n8n?
Continue On Fail is a node setting that prevents the entire workflow from stopping when that node encounters an error. Instead, the node passes the error data to the next connected node so you can handle it programmatically.
Can I have multiple levels of fallback?
Yes. Chain multiple IF nodes and LLM nodes: Primary Model → IF → Backup Model → IF → Static Fallback. Each level catches failures from the previous one.
How do I test my fallback without waiting for a real error?
Temporarily break the API credentials on the primary LLM node or change the API URL to an invalid endpoint. This forces an error so you can verify the fallback path works correctly.
Should I use the Error Trigger node instead of Continue On Fail?
They serve different purposes. Continue On Fail handles errors within the workflow so you can respond to the user. Error Trigger creates a separate workflow for logging and alerting. Use both together for the best coverage.
What error types should I handle differently?
Rate limits (429) should tell users to wait. Timeouts should suggest shorter inputs. Authentication errors should alert your team but tell users it is a temporary issue. Content policy blocks should inform the user their input cannot be processed.
Can RapidDev help me build reliable AI workflows with proper error handling?
Yes. RapidDev specializes in building production-grade n8n workflows with multi-model fallback, error logging, and monitoring. Contact RapidDev for a free consultation.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation