使用说明

n8n 工作流出错,如何通知手机

导入 n8n Error Trigger 工作流,通过 HTTPS 将错误摘要发到 Ntfyx,并用带鉴权的测试 Webhook 核对自动触发失败。

更新于

用一个处理器接收工作流失败

#

本例使用 n8n 自带的 Error Trigger、Code 与 HTTP Request 节点,无需专用 Ntfyx 节点。报告包含工作流、失败节点及可用的执行链接。默认不发送原始错误消息、堆栈或输入记录,避免其中的凭据和个人数据进入通知;完整故障仍在 n8n 查看。

先确认一条 HTTPS 通知能收到

#

截至 2026-10-29 已确认公开版为 iOS 1.8.3、Android 1.8.2。在商店更新后,按手机上的公开 Topic 或私密连接入口继续;Android 后台推送需要 Google Play 服务。 在 Ntfyx 打开 HTTPS 推送,发送 hello 测试,确认对应消息进入收件箱,再复制完整私有发送 URL。本文向固定 URL POST JSON,不需要 CLI 配对。先确认自己的手机实际收到,再配置自动化。首次设置受阻时,核对安装版本并按排障页继续。

1. 导入并设置错误处理器

#

下载错误处理器 JSON,在 n8n 使用 Import from File 导入。打开 Send to Ntfyx,将 .invalid 占位地址替换为完整 HTTPS 推送 URL;保持 POST 方法、JSON 与请求头表达式不变。保存为 Ntfyx error notifications,再到每个来源工作流的 Settings 选择它作为 Error workflow 并保存。错误处理器本身无需发布即可接收错误。

完整可导入处理器

#

Code 节点根据原始错误事件准备固定正文和标识,HTTP Request 发送该输入并记录响应状态,失败时停止且不跟随重定向。缺少稳定事件 ID 时先停止,不为不确定事件临时生成新 ID。

JSON 配置
{
  "name": "Ntfyx error notifications",
  "nodes": [
    {
      "parameters": {},
      "id": "010f3ff8-b200-46c3-9bac-a617f43e8c51",
      "name": "Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const source = $input.first().json;\nconst execution = source.execution || {};\nconst workflow = source.workflow || {};\nconst triggerError = source.trigger?.error || {};\nconst event = execution.id ? `execution-${execution.id}` : (triggerError.timestamp ? `trigger-${triggerError.timestamp}` : null);\nif (!/^[A-Za-z0-9_-]{1,64}$/.test(String(workflow.id || '')) || !event) throw new Error('No stable source event ID. Inspect and retain the original error before sending.');\nconst name = String(workflow.name || workflow.id).replace(/[\\u0000-\\u001f\\u007f]/g, ' ').trim().slice(0, 80) || String(workflow.id);\nconst lines = [`Workflow: ${name}`, `Event: ${event}`];\nif (execution.lastNodeExecuted) lines.push(`Node: ${String(execution.lastNodeExecuted).slice(0, 120)}`);\nif (execution.retryOf) lines.push(`Retry of execution: ${execution.retryOf}`);\nif (typeof execution.url === 'string' && /^https?:\\/\\//.test(execution.url)) lines.push(execution.url.slice(0, 1000));\nelse lines.push('No execution URL; inspect the workflow in n8n.');\nreturn [{json: {idempotency_key: `n8n-${workflow.id}-${event}`, payload: {title: 'n8n workflow failed', text: lines.join('\\n'), session_id: `ntfyx-n8n-${workflow.id}`.padEnd(22, '_'), session_name: name}}}];"
      },
      "id": "bb55223f-21c0-43d0-a641-2081b4fac836",
      "name": "Prepare bounded report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://replace-with-your-private-ntfyx-url.invalid/",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Idempotency-Key",
              "value": "={{ $json.idempotency_key }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.payload) }}",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": false,
              "responseFormat": "json"
            }
          },
          "timeout": 15000
        }
      },
      "id": "f6af45c3-e92b-4775-9053-7226964ce3d8",
      "name": "Send to Ntfyx",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        480,
        0
      ],
      "retryOnFail": false,
      "onError": "stopWorkflow",
      "notes": "Replace the URL privately with the complete HTTPS Push URL copied from Ntfyx. The full URL is a send-only secret; scrub it before sharing any workflow export. Automatic retries are disabled: after an uncertain send, retain this node's exact input and Idempotency-Key; inspect Retry-After before retrying."
    }
  ],
  "connections": {
    "Error Trigger": {
      "main": [
        [
          {
            "node": "Prepare bounded report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare bounded report": {
      "main": [
        [
          {
            "node": "Send to Ntfyx",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "tags": []
}

2. 触发一次自动执行的无副作用失败

#

手动点击 Execute Workflow 不会触发错误工作流。导入下方独立测试 JSON:带鉴权的 POST Webhook 连接 Stop And Error。为 Webhook 创建 Header Auth 凭据,Name 为 X-Ntfyx-Demo-Key,Value 使用新生成的私有随机值,并设置自己的路径。将测试工作流的 Error workflow 指向 Ntfyx error notifications。仅发布或启用此测试工作流,再复制其 Production URL。

终端
# Set N8N_TEST_URL and N8N_TEST_KEY privately first.
curl --fail --silent --show-error --request POST "$N8N_TEST_URL" \
  --header "X-Ntfyx-Demo-Key: $N8N_TEST_KEY" \
  --header "Content-Type: application/json" \
  --data '{"tutorial":"ntfyx-error-test"}'

3. 对照三个结果

#

先找到失败的来源执行,再找到 Send to Ntfyx 返回 2xx 的错误处理执行,最后在手机收件箱找到“n8n workflow failed”。消息应指向测试工作流和 Intentional failure 节点,执行 ID 与链接一致。手机横幅另外检查。来源触发器本身出错时可能没有保存的执行 URL;报告会说明,并在可用时使用触发错误的时间戳标识。

观察到的状态下一步检查
来源失败,但没有处理器执行确认是自动执行,并核对来源的 Error workflow 设置。
HTTP 节点失败检查私有 URL、Topic 状态、额度与 HTTP 错误;保留原始输入。
2xx,但收件箱没有消息检查目标 Topic、同步与手机网络。
收件箱有消息,但没有提醒检查通知权限、静音与免打扰时段。

重试通知,不重新执行业务任务

#

模板关闭自动 Retry On Fail。429 或 503 按 Retry-After 等待;超时表示发送结果未知。先核对手机和失败的处理器,再用保存的原样输入与 Idempotency-Key 重试 Send to Ntfyx。不要为了补发提醒而重新运行来源业务。401/403 鉴权或权限错误需先修正。保留 n8n Executions 中的失败记录;此处理器不能代替对 n8n 自身的监控。

验证范围与下一步

#

两个文件已在本地检查 JSON 结构和节点连接;报告代码覆盖已保存执行、重试、触发器错误及缺失 ID 夹具,并用 Ntfyx Webhook 解析器核对。此模板尚未在运行中的 n8n 实例完成导入和实体手机收件验收;用于真实工作流前请完成上述自动测试。HTTPS 通知只报告错误;任务必须等待验签的人类回答时,使用受保护 Topic 的 Agent 应答流程。