{
  "updatedAt": "2026-05-14T00:18:01.110Z",
  "createdAt": "2026-05-12T16:59:40.394Z",
  "id": "G9ylNbHbnJ6fWX2C",
  "name": "n8n Failure Digest",
  "description": null,
  "active": true,
  "isArchived": false,
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -920,
        -120
      ],
      "id": "a673b342-0e9e-44ae-a470-0a7ba93d135e",
      "name": "Manual Trigger"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 10 * * * *"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -920,
        80
      ],
      "id": "6b8a395f-eadd-479d-980d-6f744f411c7d",
      "name": "Hourly Schedule"
    },
    {
      "parameters": {
        "url": "http://127.0.0.1:5678/api/v1/executions?status=error&limit=100",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -660,
        0
      ],
      "id": "afbf364e-4aca-4c7f-a43a-62a5e0b05d3b",
      "name": "List Failed Executions",
      "credentials": {
        "httpHeaderAuth": {
          "id": "UPAHgUJVRqZQceL4",
          "name": "n8n Public API (Failure Digest)"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const data = Array.isArray($json.data) ? $json.data : [];\nconst windowMinutes = 65;\nconst cutoff = Date.now() - windowMinutes * 60 * 1000;\nconst selfName = 'n8n Failure Digest';\nconst seen = new Set();\nconst out = [];\nfor (const ex of data) {\n  const status = String(ex.status || '').toLowerCase();\n  if (!['error', 'crashed'].includes(status)) continue;\n  const t = Date.parse(ex.stoppedAt || ex.startedAt || ex.createdAt || '');\n  if (Number.isFinite(t) && t < cutoff) continue;\n  const id = String(ex.id || '');\n  if (!id || seen.has(id)) continue;\n  seen.add(id);\n  out.push({ json: { id, status, startedAt: ex.startedAt, stoppedAt: ex.stoppedAt, workflowId: ex.workflowId, windowMinutes } });\n}\nreturn out;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -420,
        0
      ],
      "id": "00f4d7aa-3890-4eb4-bcb4-64afd7675767",
      "name": "Recent Failure IDs"
    },
    {
      "parameters": {
        "url": "=http://127.0.0.1:5678/api/v1/executions/{{$json.id}}?includeData=true",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -180,
        0
      ],
      "id": "4de4125e-75d6-4896-93d1-1ce20dce2db8",
      "name": "Fetch Failure Details",
      "credentials": {
        "httpHeaderAuth": {
          "id": "UPAHgUJVRqZQceL4",
          "name": "n8n Public API (Failure Digest)"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nconst windowMinutes = 65;\nconst now = Date.now();\nconst selfName = 'n8n Failure Digest';\nfunction arr(v) { return Array.isArray(v) ? v : (v == null ? [] : [v]); }\nfunction msg(err) {\n  if (!err) return 'Unknown error';\n  return String(err.message || err.description || err.name || err.code || JSON.stringify(err)).trim() || 'Unknown error';\n}\nfunction errType(err) { return String(err?.name || err?.type || err?.code || err?.httpCode || 'Error'); }\nfunction sig(s) {\n  return String(s).split('\\n')[0]\n    .replace(/https?:\\/\\/\\S+/g, '<url>')\n    .replace(/[0-9a-f]{8,}/gi, '<hex>')\n    .replace(/\\b\\d{4,}\\b/g, '<num>')\n    .slice(0, 180);\n}\nfunction findErr(ex) {\n  const rd = ex.data?.resultData || {};\n  if (rd.error) return { node: rd.error.node?.name || rd.error.node || rd.lastNodeExecuted || 'unknown', error: rd.error };\n  const runData = rd.runData || {};\n  for (const [nodeName, attempts] of Object.entries(runData)) {\n    for (const attempt of arr(attempts).slice().reverse()) {\n      if (attempt?.error) return { node: nodeName, error: attempt.error };\n    }\n  }\n  return { node: rd.lastNodeExecuted || 'unknown', error: ex.error || {} };\n}\nconst failures = [];\nfor (const item of items) {\n  const ex = item.json || {};\n  const workflowName = ex.workflowData?.name || ex.workflow?.name || `Workflow ${ex.workflowId || 'unknown'}`;\n  if (workflowName === selfName) continue;\n  const found = findErr(ex);\n  const message = msg(found.error);\n  const when = ex.stoppedAt || ex.startedAt || ex.createdAt || new Date(now).toISOString();\n  failures.push({\n    id: ex.id,\n    workflowId: ex.workflowId || ex.workflowData?.id || 'unknown',\n    workflowName,\n    node: found.node || 'unknown',\n    errorType: errType(found.error),\n    message,\n    signature: sig(message),\n    when,\n    status: ex.status || 'unknown',\n  });\n}\nconst groups = new Map();\nfor (const f of failures) {\n  const key = `${f.workflowId}\\u0000${f.node}\\u0000${f.errorType}\\u0000${f.signature}`;\n  if (!groups.has(key)) groups.set(key, { workflowName: f.workflowName, workflowId: f.workflowId, node: f.node, errorType: f.errorType, signature: f.signature, count: 0, ids: [], latest: f.when });\n  const g = groups.get(key);\n  g.count++;\n  if (g.ids.length < 8) g.ids.push(f.id);\n  if (String(f.when) > String(g.latest)) g.latest = f.when;\n}\nconst sorted = [...groups.values()].sort((a,b) => b.count - a.count || String(b.latest).localeCompare(String(a.latest))).slice(0, 12);\nif (!sorted.length) return [];\nfunction telegramSafe(s) { return String(s || '').replace(/[\\u0000-\\u001f\\u007f]/g, ' ').slice(0, 3500); }\nconst lines = [];\nlines.push(`🚨 n8n Failure Digest: ${failures.length} failed execution(s) in the last ${windowMinutes} min`);\nlines.push('');\nsorted.forEach((g, i) => {\n  lines.push(`${i+1}. ${g.workflowName}`);\n  lines.push(`   Node: ${g.node}`);\n  lines.push(`   ${g.count}x ${g.errorType}: ${g.signature}`);\n  lines.push(`   Execs: ${g.ids.join(', ')} | latest ${g.latest}`);\n});\nlines.push('');\nlines.push('Open n8n: http://127.0.0.1:18808');\n// Telegram node defaults to legacy Markdown, so escape characters that\n// commonly occur in workflow/node/error names (notably underscores).\nfunction telegramMarkdownSafe(s) { return String(s).replace(/([_*`\\[])/g, '\\\\$1'); }\nconst text = telegramMarkdownSafe(lines.join('\\n'));\nreturn [{ json: { text, totalFailures: failures.length, groups: sorted, generatedAt: new Date(now).toISOString() } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        80,
        0
      ],
      "id": "f6b4eab8-7017-43e6-97c8-dce63873e097",
      "name": "Build Digest"
    },
    {
      "parameters": {
        "chatId": "8367012007",
        "text": "={{ $json.text }}",
        "additionalFields": {
          "parse_mode": "",
          "disable_web_page_preview": true
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        340,
        0
      ],
      "id": "cf49d05d-5d81-404b-a751-ce56794985a9",
      "name": "Send Telegram Digest",
      "credentials": {
        "telegramApi": {
          "id": "aox4dyIWVSRdcH5z",
          "name": "Telegram Bot (OpenClaw)"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://discord.com/api/v10/channels/1494453542243532932/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ content: $json.text.substring(0, 2000) }) }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        340,
        200
      ],
      "id": "6c3086e4-0869-4003-94c3-66b4975f94e9",
      "name": "Send Discord Digest",
      "credentials": {
        "httpHeaderAuth": {
          "id": "UgPqYcoCNNIgr55m",
          "name": "Discord Bot Auth"
        }
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "List Failed Executions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hourly Schedule": {
      "main": [
        [
          {
            "node": "List Failed Executions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List Failed Executions": {
      "main": [
        [
          {
            "node": "Recent Failure IDs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recent Failure IDs": {
      "main": [
        [
          {
            "node": "Fetch Failure Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Failure Details": {
      "main": [
        [
          {
            "node": "Build Digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Digest": {
      "main": [
        [
          {
            "node": "Send Telegram Digest",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Discord Digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "timezone": "America/Los_Angeles",
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "none",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false
  },
  "staticData": {
    "node:Hourly Schedule": {
      "recurrenceRules": []
    }
  },
  "meta": null,
  "versionId": "2d85e3bf-d8cf-4274-bf61-5377241897da",
  "activeVersionId": "2d85e3bf-d8cf-4274-bf61-5377241897da",
  "versionCounter": 36,
  "triggerCount": 1,
  "shared": [
    {
      "updatedAt": "2026-05-12T16:59:40.395Z",
      "createdAt": "2026-05-12T16:59:40.395Z",
      "role": "workflow:owner",
      "workflowId": "G9ylNbHbnJ6fWX2C",
      "projectId": "WGdp8QunI1tHpjXa",
      "project": {
        "updatedAt": "2026-03-11T21:08:10.005Z",
        "createdAt": "2026-03-11T21:05:11.541Z",
        "id": "WGdp8QunI1tHpjXa",
        "name": "will will <will@wills-portal.com>",
        "type": "personal",
        "icon": null,
        "description": null,
        "creatorId": "5ad50ead-6e6a-4d12-ab5b-e5db15835bb5"
      }
    }
  ],
  "tags": [],
  "activeVersion": {
    "updatedAt": "2026-05-14T00:18:01.111Z",
    "createdAt": "2026-05-14T00:18:01.111Z",
    "versionId": "2d85e3bf-d8cf-4274-bf61-5377241897da",
    "workflowId": "G9ylNbHbnJ6fWX2C",
    "nodes": [
      {
        "parameters": {},
        "type": "n8n-nodes-base.manualTrigger",
        "typeVersion": 1,
        "position": [
          -920,
          -120
        ],
        "id": "a673b342-0e9e-44ae-a470-0a7ba93d135e",
        "name": "Manual Trigger"
      },
      {
        "parameters": {
          "rule": {
            "interval": [
              {
                "field": "cronExpression",
                "expression": "0 10 * * * *"
              }
            ]
          }
        },
        "type": "n8n-nodes-base.scheduleTrigger",
        "typeVersion": 1.3,
        "position": [
          -920,
          80
        ],
        "id": "6b8a395f-eadd-479d-980d-6f744f411c7d",
        "name": "Hourly Schedule"
      },
      {
        "parameters": {
          "url": "http://127.0.0.1:5678/api/v1/executions?status=error&limit=100",
          "authentication": "genericCredentialType",
          "genericAuthType": "httpHeaderAuth",
          "options": {}
        },
        "type": "n8n-nodes-base.httpRequest",
        "typeVersion": 4.2,
        "position": [
          -660,
          0
        ],
        "id": "afbf364e-4aca-4c7f-a43a-62a5e0b05d3b",
        "name": "List Failed Executions",
        "credentials": {
          "httpHeaderAuth": {
            "id": "UPAHgUJVRqZQceL4",
            "name": "n8n Public API (Failure Digest)"
          }
        }
      },
      {
        "parameters": {
          "mode": "runOnceForAllItems",
          "jsCode": "const data = Array.isArray($json.data) ? $json.data : [];\nconst windowMinutes = 65;\nconst cutoff = Date.now() - windowMinutes * 60 * 1000;\nconst selfName = 'n8n Failure Digest';\nconst seen = new Set();\nconst out = [];\nfor (const ex of data) {\n  const status = String(ex.status || '').toLowerCase();\n  if (!['error', 'crashed'].includes(status)) continue;\n  const t = Date.parse(ex.stoppedAt || ex.startedAt || ex.createdAt || '');\n  if (Number.isFinite(t) && t < cutoff) continue;\n  const id = String(ex.id || '');\n  if (!id || seen.has(id)) continue;\n  seen.add(id);\n  out.push({ json: { id, status, startedAt: ex.startedAt, stoppedAt: ex.stoppedAt, workflowId: ex.workflowId, windowMinutes } });\n}\nreturn out;"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          -420,
          0
        ],
        "id": "00f4d7aa-3890-4eb4-bcb4-64afd7675767",
        "name": "Recent Failure IDs"
      },
      {
        "parameters": {
          "url": "=http://127.0.0.1:5678/api/v1/executions/{{$json.id}}?includeData=true",
          "authentication": "genericCredentialType",
          "genericAuthType": "httpHeaderAuth",
          "options": {}
        },
        "type": "n8n-nodes-base.httpRequest",
        "typeVersion": 4.2,
        "position": [
          -180,
          0
        ],
        "id": "4de4125e-75d6-4896-93d1-1ce20dce2db8",
        "name": "Fetch Failure Details",
        "credentials": {
          "httpHeaderAuth": {
            "id": "UPAHgUJVRqZQceL4",
            "name": "n8n Public API (Failure Digest)"
          }
        }
      },
      {
        "parameters": {
          "mode": "runOnceForAllItems",
          "jsCode": "const items = $input.all();\nconst windowMinutes = 65;\nconst now = Date.now();\nconst selfName = 'n8n Failure Digest';\nfunction arr(v) { return Array.isArray(v) ? v : (v == null ? [] : [v]); }\nfunction msg(err) {\n  if (!err) return 'Unknown error';\n  return String(err.message || err.description || err.name || err.code || JSON.stringify(err)).trim() || 'Unknown error';\n}\nfunction errType(err) { return String(err?.name || err?.type || err?.code || err?.httpCode || 'Error'); }\nfunction sig(s) {\n  return String(s).split('\\n')[0]\n    .replace(/https?:\\/\\/\\S+/g, '<url>')\n    .replace(/[0-9a-f]{8,}/gi, '<hex>')\n    .replace(/\\b\\d{4,}\\b/g, '<num>')\n    .slice(0, 180);\n}\nfunction findErr(ex) {\n  const rd = ex.data?.resultData || {};\n  if (rd.error) return { node: rd.error.node?.name || rd.error.node || rd.lastNodeExecuted || 'unknown', error: rd.error };\n  const runData = rd.runData || {};\n  for (const [nodeName, attempts] of Object.entries(runData)) {\n    for (const attempt of arr(attempts).slice().reverse()) {\n      if (attempt?.error) return { node: nodeName, error: attempt.error };\n    }\n  }\n  return { node: rd.lastNodeExecuted || 'unknown', error: ex.error || {} };\n}\nconst failures = [];\nfor (const item of items) {\n  const ex = item.json || {};\n  const workflowName = ex.workflowData?.name || ex.workflow?.name || `Workflow ${ex.workflowId || 'unknown'}`;\n  if (workflowName === selfName) continue;\n  const found = findErr(ex);\n  const message = msg(found.error);\n  const when = ex.stoppedAt || ex.startedAt || ex.createdAt || new Date(now).toISOString();\n  failures.push({\n    id: ex.id,\n    workflowId: ex.workflowId || ex.workflowData?.id || 'unknown',\n    workflowName,\n    node: found.node || 'unknown',\n    errorType: errType(found.error),\n    message,\n    signature: sig(message),\n    when,\n    status: ex.status || 'unknown',\n  });\n}\nconst groups = new Map();\nfor (const f of failures) {\n  const key = `${f.workflowId}\\u0000${f.node}\\u0000${f.errorType}\\u0000${f.signature}`;\n  if (!groups.has(key)) groups.set(key, { workflowName: f.workflowName, workflowId: f.workflowId, node: f.node, errorType: f.errorType, signature: f.signature, count: 0, ids: [], latest: f.when });\n  const g = groups.get(key);\n  g.count++;\n  if (g.ids.length < 8) g.ids.push(f.id);\n  if (String(f.when) > String(g.latest)) g.latest = f.when;\n}\nconst sorted = [...groups.values()].sort((a,b) => b.count - a.count || String(b.latest).localeCompare(String(a.latest))).slice(0, 12);\nif (!sorted.length) return [];\nfunction telegramSafe(s) { return String(s || '').replace(/[\\u0000-\\u001f\\u007f]/g, ' ').slice(0, 3500); }\nconst lines = [];\nlines.push(`🚨 n8n Failure Digest: ${failures.length} failed execution(s) in the last ${windowMinutes} min`);\nlines.push('');\nsorted.forEach((g, i) => {\n  lines.push(`${i+1}. ${g.workflowName}`);\n  lines.push(`   Node: ${g.node}`);\n  lines.push(`   ${g.count}x ${g.errorType}: ${g.signature}`);\n  lines.push(`   Execs: ${g.ids.join(', ')} | latest ${g.latest}`);\n});\nlines.push('');\nlines.push('Open n8n: http://127.0.0.1:18808');\n// Telegram node defaults to legacy Markdown, so escape characters that\n// commonly occur in workflow/node/error names (notably underscores).\nfunction telegramMarkdownSafe(s) { return String(s).replace(/([_*`\\[])/g, '\\\\$1'); }\nconst text = telegramMarkdownSafe(lines.join('\\n'));\nreturn [{ json: { text, totalFailures: failures.length, groups: sorted, generatedAt: new Date(now).toISOString() } }];"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          80,
          0
        ],
        "id": "f6b4eab8-7017-43e6-97c8-dce63873e097",
        "name": "Build Digest"
      },
      {
        "parameters": {
          "chatId": "8367012007",
          "text": "={{ $json.text }}",
          "additionalFields": {
            "parse_mode": "",
            "disable_web_page_preview": true
          }
        },
        "type": "n8n-nodes-base.telegram",
        "typeVersion": 1,
        "position": [
          340,
          0
        ],
        "id": "cf49d05d-5d81-404b-a751-ce56794985a9",
        "name": "Send Telegram Digest",
        "credentials": {
          "telegramApi": {
            "id": "aox4dyIWVSRdcH5z",
            "name": "Telegram Bot (OpenClaw)"
          }
        }
      },
      {
        "parameters": {
          "method": "POST",
          "url": "https://discord.com/api/v10/channels/1494453542243532932/messages",
          "authentication": "genericCredentialType",
          "genericAuthType": "httpHeaderAuth",
          "sendBody": true,
          "specifyBody": "json",
          "jsonBody": "={{ JSON.stringify({ content: $json.text.substring(0, 2000) }) }}",
          "options": {
            "response": {
              "response": {
                "responseFormat": "text"
              }
            }
          }
        },
        "type": "n8n-nodes-base.httpRequest",
        "typeVersion": 4.2,
        "position": [
          340,
          200
        ],
        "id": "6c3086e4-0869-4003-94c3-66b4975f94e9",
        "name": "Send Discord Digest",
        "credentials": {
          "httpHeaderAuth": {
            "id": "UgPqYcoCNNIgr55m",
            "name": "Discord Bot Auth"
          }
        }
      }
    ],
    "connections": {
      "Manual Trigger": {
        "main": [
          [
            {
              "node": "List Failed Executions",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Hourly Schedule": {
        "main": [
          [
            {
              "node": "List Failed Executions",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "List Failed Executions": {
        "main": [
          [
            {
              "node": "Recent Failure IDs",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Recent Failure IDs": {
        "main": [
          [
            {
              "node": "Fetch Failure Details",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Fetch Failure Details": {
        "main": [
          [
            {
              "node": "Build Digest",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Build Digest": {
        "main": [
          [
            {
              "node": "Send Telegram Digest",
              "type": "main",
              "index": 0
            },
            {
              "node": "Send Discord Digest",
              "type": "main",
              "index": 0
            }
          ]
        ]
      }
    },
    "authors": "will will",
    "name": null,
    "description": null,
    "autosaved": false,
    "workflowPublishHistory": [
      {
        "createdAt": "2026-05-14T00:18:01.158Z",
        "id": 1491,
        "workflowId": "G9ylNbHbnJ6fWX2C",
        "versionId": "2d85e3bf-d8cf-4274-bf61-5377241897da",
        "event": "activated",
        "userId": "5ad50ead-6e6a-4d12-ab5b-e5db15835bb5"
      }
    ]
  }
}
