Skip to main content

Error Handling

n8n provides comprehensive error handling mechanisms at multiple levels: node-level, workflow-level, and system-level. Understanding these mechanisms helps you build resilient workflows that gracefully handle failures.

Error Types

n8n uses a hierarchical error system with specific error classes:

Node Errors

Errors that occur during node execution:
// From errors/node-operation.error.ts
export class NodeOperationError extends NodeError {
  constructor(
    node: INode,
    error: Error | string | JsonObject,
    options: NodeOperationErrorOptions = {}
  ) {
    // Error context
    this.context.runIndex = options.runIndex;
    this.context.itemIndex = options.itemIndex;
    this.context.metadata = options.metadata;
    
    // Severity level
    this.level = options.level ?? 'warning';
  }
}
When to use:
  • Invalid credentials
  • API rate limiting
  • Invalid parameters
  • Business logic errors
Example:
throw new NodeOperationError(
  this.getNode(),
  'Invalid API key provided',
  {
    itemIndex: i,
    description: 'Check your API credentials in node settings'
  }
);

Node-Level Error Handling

Retry Configuration

Nodes can automatically retry on failure:
const node: INode = {
  name: 'HTTP Request',
  type: 'n8n-nodes-base.httpRequest',
  typeVersion: 1,
  position: [450, 300],
  parameters: {
    url: 'https://api.example.com/data'
  },
  // Retry configuration
  retryOnFail: true,
  maxTries: 3,
  waitBetweenTries: 1000  // milliseconds
};
1

First Attempt

Node executes normally. If it succeeds, execution continues.
2

Failure Detected

If the node throws an error and retryOnFail is true, the retry mechanism activates.
3

Wait Period

System waits for waitBetweenTries milliseconds before retrying.
4

Retry Attempts

Node executes again. This continues up to maxTries times.
5

Final Result

  • If any attempt succeeds, execution continues
  • If all attempts fail, error handling logic applies

Continue on Fail

Control whether workflow execution stops on node failure:
const node: INode = {
  name: 'Optional API Call',
  type: 'n8n-nodes-base.httpRequest',
  typeVersion: 1,
  position: [450, 300],
  parameters: {},
  continueOnFail: true,      // Don't stop workflow
  alwaysOutputData: true     // Output data even on error
};
const node = {
  continueOnFail: false,
  alwaysOutputData: false
};
// Behavior:
// - Error thrown
// - Workflow execution stops
// - Error workflow triggered (if configured)
// - No data passed to next nodes

Error Data Structure

When alwaysOutputData is true, failed items include error information:
interface INodeExecutionData {
  json: IDataObject;
  error?: {
    message: string;
    stack?: string;
    context?: {
      itemIndex?: number;
      runIndex?: number;
      parameter?: string;
    };
  };
}

// Example error data
const errorOutput: INodeExecutionData = {
  json: {
    // Original input data
    id: 123,
    url: 'https://api.example.com/user/123'
  },
  error: {
    message: 'Request failed with status code 404',
    context: {
      itemIndex: 2,
      runIndex: 0
    }
  }
};

Workflow-Level Error Handling

Error Workflow

Configure a dedicated error workflow to handle failures:
const workflowSettings: IWorkflowSettings = {
  errorWorkflow: 'error-handler-workflow-id'
};
The error workflow receives:
interface IExecutionError {
  execution: {
    id: string;
    mode: WorkflowExecuteMode;
    startedAt: Date;
    workflowId: string;
    workflowName: string;
  };
  workflow: {
    id: string;
    name: string;
  };
  node: {
    name: string;
    type: string;
    parameters: INodeParameters;
  };
  error: {
    message: string;
    stack?: string;
    context?: IDataObject;
  };
}
Error workflows run in error mode and receive the complete error context, allowing you to:
  • Send error notifications (email, Slack, etc.)
  • Log errors to external services
  • Trigger recovery workflows
  • Store error details for analysis

Error Trigger Node

The Error Trigger node starts workflows when errors occur:
// Error Trigger configuration
const errorTrigger: INode = {
  name: 'Error Trigger',
  type: 'n8n-nodes-base.errorTrigger',
  typeVersion: 1,
  position: [250, 300],
  parameters: {}
};

// Next node can access error data
const emailNode: INode = {
  name: 'Send Email',
  type: 'n8n-nodes-base.emailSend',
  typeVersion: 1,
  position: [450, 300],
  parameters: {
    subject: '={{"Workflow Error: " + $json.workflow.name}}',
    text: '={{$json.error.message}}',
    html: `={
      Workflow: {{$json.workflow.name}}<br>
      Node: {{$json.node.name}}<br>
      Error: {{$json.error.message}}<br>
      Time: {{$json.execution.startedAt}}
    }`
  }
};

Execution-Level Error Handling

Execution Errors

The execution engine tracks errors throughout workflow execution:
// From workflow-execute.ts
interface IRun {
  data: IRunData;
  mode: WorkflowExecuteMode;
  startedAt: Date;
  stoppedAt?: Date;
  status: ExecutionStatus;  // 'new', 'running', 'success', 'error', 'canceled'
  error?: ExecutionError;
}

// Execution status values
type ExecutionStatus = 
  | 'new'       // Just created
  | 'running'   // Currently executing
  | 'success'   // Completed successfully
  | 'error'     // Failed with error
  | 'waiting'   // Waiting for external event
  | 'canceled'; // Manually canceled

Timeout Handling

const workflowSettings: IWorkflowSettings = {
  executionTimeout: 3600  // seconds
};

// From workflow-execute.ts
class WorkflowExecute {
  timedOut: boolean = false;
  
  // Timeout causes execution to cancel
  // Throws: TimeoutExecutionCancelledError
}

Manual Cancellation

// Cancel an active execution
workflowExecute.abortController.abort();

// Throws: ManualExecutionCancelledError

Error Recovery Patterns

Pattern 1: Graceful Degradation

Continue with default values when optional operations fail:
// In IF node or expression
{{
  $node["Optional API"].json !== undefined
    ? $node["Optional API"].json.data
    : { defaultValue: true }
}}

Pattern 2: Error Notification

Notify team when critical operations fail:
1

Configure Error Workflow

Set error workflow in workflow settings
2

Add Error Trigger

Start error workflow with Error Trigger node
3

Send Notification

Use Slack, Email, or webhook to alert team

Pattern 3: Fallback Service

Try alternate services if primary fails:
// Primary service node
const primaryNode: INode = {
  name: 'Primary API',
  continueOnFail: true,
  alwaysOutputData: true
};

// IF node checks for error
const ifNode: INode = {
  name: 'Check Error',
  parameters: {
    conditions: {
      boolean: [
        {
          value1: '={{$json.error !== undefined}}',
          operation: 'equal',
          value2: true
        }
      ]
    }
  }
};

// Fallback service on true branch
const fallbackNode: INode = {
  name: 'Fallback API'
};

Pattern 4: Exponential Backoff

Implement custom retry with increasing delays:
// In Code node
const maxRetries = 5;
let attempt = 0;
let success = false;
let data = null;

while (attempt < maxRetries && !success) {
  try {
    data = await makeRequest();
    success = true;
  } catch (error) {
    attempt++;
    if (attempt < maxRetries) {
      const delay = Math.pow(2, attempt) * 1000;  // 2s, 4s, 8s, 16s, 32s
      await new Promise(resolve => setTimeout(resolve, delay));
    } else {
      throw error;
    }
  }
}

return { json: data };

Error Context and Debugging

Error Context Information

Errors include detailed context for debugging:
class NodeError extends Error {
  node: INode;
  context: {
    itemIndex?: number;      // Which item failed
    runIndex?: number;        // Which execution run
    parameter?: string;       // Which parameter caused error
    data?: IDataObject;      // Additional context
  };
  description?: string;       // User-friendly description
  httpCode?: string;         // HTTP status code
  cause?: Error;             // Original error
}

Accessing Error Details

In error workflows or subsequent nodes:
// Error message
{{$json.error.message}}

// Stack trace
{{$json.error.stack}}

// Failed node information
{{$json.node.name}}
{{$json.node.type}}

// Execution context
{{$json.execution.mode}}
{{$json.execution.startedAt}}

// Item that caused error
{{$json.error.context.itemIndex}}

Best Practices

  1. Set appropriate retry counts: Too many retries can delay error detection
  2. Use meaningful error messages: Include context for debugging
  3. Configure error workflows: Set up centralized error handling
  4. Handle errors close to source: Use continueOnFail judiciously
  5. Log errors appropriately: Balance detail with noise
  6. Test error scenarios: Deliberately trigger errors to test handling
  7. Document error handling: Explain expected failures in workflow notes
  8. Monitor error rates: Track and alert on unusual error patterns
Testing Error Handling:
  1. Use the “Test workflow” button with invalid data
  2. Temporarily set incorrect credentials to test auth errors
  3. Use the IF node to simulate random failures
  4. Test timeout behavior with long-running operations
  5. Verify error workflows receive correct data

Common Error Scenarios

API Rate Limiting

const node: INode = {
  retryOnFail: true,
  maxTries: 5,
  waitBetweenTries: 60000  // Wait 1 minute between retries
};

Transient Network Errors

const node: INode = {
  retryOnFail: true,
  maxTries: 3,
  waitBetweenTries: 5000  // Wait 5 seconds
};

Optional Operations

const node: INode = {
  continueOnFail: true,
  alwaysOutputData: false  // Don't pass error data forward
};

Critical Operations

const node: INode = {
  retryOnFail: true,
  maxTries: 3,
  continueOnFail: false  // Stop on failure
};

const workflowSettings: IWorkflowSettings = {
  errorWorkflow: 'critical-error-handler'  // Alert team immediately
};

Next Steps

Execution Modes

Understand how workflows execute in different contexts

Creating Workflows

Learn more about workflow structure and design