{
  "name": "Error Handler",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "error-handler",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-trigger",
      "name": "Error Input",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Classify error\nconst error = $input.first().json.body || $input.first().json;\n\n// Error classification rules\nfunction classifyError(err) {\n  const message = (err.message || '').toLowerCase();\n  const statusCode = err.statusCode || err.status;\n\n  if (statusCode === 429 || message.includes('rate limit')) {\n    return { type: 'RATE_LIMIT', retryable: true, critical: false };\n  }\n  if (statusCode >= 500 || message.includes('timeout') || message.includes('network')) {\n    return { type: 'NETWORK', retryable: true, critical: false };\n  }\n  if (statusCode === 401 || statusCode === 403 || message.includes('auth')) {\n    return { type: 'AUTH', retryable: false, critical: true };\n  }\n  if (message.includes('validation') || message.includes('invalid')) {\n    return { type: 'VALIDATION', retryable: false, critical: false };\n  }\n  \n  return { type: 'UNKNOWN', retryable: false, critical: false };\n}\n\nconst classification = classifyError(error);\n\n// Calculate retry delay (exponential backoff)\nconst attempt = error.attempt || 0;\nconst baseDelay = 1000;\nconst maxDelay = 60000;\nconst delay = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);\n\n// Determine action\nconst shouldRetry = classification.retryable && attempt < 5;\nconst shouldNotify = classification.critical;\nconst shouldFallback = !shouldRetry && !classification.retryable;\n\nreturn {\n  originalError: error,\n  classification,\n  retry: {\n    should: shouldRetry,\n    delay,\n    attempt: attempt + 1,\n    maxAttempts: 5\n  },\n  notify: shouldNotify,\n  fallback: shouldFallback,\n  timestamp: new Date().toISOString()\n};"
      },
      "id": "classify-node",
      "name": "Classify Error",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "leftValue": "={{ $json.notify }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ]
        }
      },
      "id": "should-notify",
      "name": "Critical?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "channel": "#alerts",
        "text": "={{ '\ud83d\udea8 Critical Error: ' + $json.classification.type }}",
        "otherOptions": {}
      },
      "id": "slack-notify",
      "name": "Notify Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 1,
      "position": [
        850,
        200
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "SETUP_REQUIRED",
          "mode": "id"
        },
        "sheetName": "Sheet1",
        "columns": {
          "mappingMode": "autoMapInputData"
        }
      },
      "id": "log-sheets",
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [
        850,
        400
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: false, classification: $json.classification, retry: $json.retry, fallback: $json.fallback }) }}",
        "options": {}
      },
      "id": "respond-node",
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1050,
        300
      ]
    }
  ],
  "connections": {
    "Error Input": {
      "main": [
        [
          {
            "node": "Classify Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Error": {
      "main": [
        [
          {
            "node": "Critical?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Critical?": {
      "main": [
        [
          {
            "node": "Notify Slack",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Slack": {
      "main": [
        [
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Sheets": {
      "main": [
        [
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 0,
  "updatedAt": "2026-03-02T19:00:00.000Z",
  "versionId": "1"
}