Overview
The catch node intercepts errors thrown by other nodes in the same flow.
When a node fails — whether from a network timeout, invalid data, or runtime exception — the catch node
receives the error details in msg.error along with the original message.
This enables retry logic, error logging, notifications, and graceful degradation patterns.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| scope | string | "all" | "all" catches from all nodes; "target" catches only from specified nodes |
| nodeIds | array | [] | List of node IDs to catch errors from (when scope = "target") |
| uncaught | boolean | false | Only catch errors not already handled by a targeted catch node |
Error Object Structure
msg.error
Error details attached to the caught message
msg.error = {
"message": "ECONNREFUSED",
"source": {
"id": "node-abc123",
"type": "http request",
"name": "Call API"
}
} Original Message
The original msg that caused the error is preserved
// msg.payload still contains the
// original data that was being
// processed when the error occurred.
// msg.topic is also preserved.
// msg._msgid identifies the message. Scope: All Nodes
Catches errors from every node in the flow
// scope: "all"
// Acts as a global error handler.
// Good for logging all errors to
// a central location. Scope: Target Nodes
Catches errors only from specific nodes
// scope: "target"
// nodeIds: ["http-req-1", "db-write-1"]
// Only catches errors from the
// specified HTTP and DB nodes. Example: Retry Failed HTTP Requests
Catch HTTP request failures and retry up to 3 times with exponential backoff.
// Catch node configuration — target the HTTP request node
{
"scope": "target",
"nodeIds": ["http-request-node-id"]
}
// Function node after catch — retry logic:
{
"code": "msg.retryCount = (msg.retryCount || 0) + 1;\nif (msg.retryCount <= 3) {\n msg.delay = Math.pow(2, msg.retryCount) * 1000;\n delete msg.error;\n return msg; // Route back to delay → HTTP request\n}\nmsg.payload = {\n error: msg.error.message,\n failedAfter: msg.retryCount + ' attempts',\n originalPayload: msg.payload\n};\nreturn msg; // Route to error notification"
}
// Flow: HTTP Request → (success) → output
// HTTP Request → catch → function → delay → HTTP Request (retry)
// → (max retries) → notification Example: Error Notification Flow
Catch all errors in a flow and send a formatted Slack/email notification.
// Catch node configuration — catch all errors
{
"scope": "all",
"uncaught": false
}
// Template node — format error notification
{
"template": "⚠️ EdgeFlow Error\n\nNode: {{error.source.name}} ({{error.source.type}})\nError: {{error.message}}\nTopic: {{topic}}\nTime: {{payload.timestamp}}"
}
// Caught error message
{
"topic": "sensors/temperature",
"payload": { "value": 42.5, "timestamp": "2025-06-15T14:30:00Z" },
"error": {
"message": "ECONNREFUSED 10.0.1.50:5432",
"source": {
"id": "db-write-01",
"type": "postgres",
"name": "Write to TimescaleDB"
}
}
}
// Formatted output → send via HTTP POST to Slack webhook Example: Graceful Degradation with Fallback
If the primary database is unreachable, fall back to local file storage.
// Catch node — target the database node
{
"scope": "target",
"nodeIds": ["postgres-node-id"]
}
// Function node — prepare fallback
{
"code": "// Remove error, keep original payload\nconst data = msg.payload;\ndelete msg.error;\nmsg.payload = JSON.stringify(data) + '\\n';\nmsg.filename = '/var/edgeflow/fallback/data.jsonl';\nreturn msg;"
}
// Flow:
// sensor → postgres node → (success, stored in DB)
// postgres node → catch → function → file write node
//
// Data is never lost — falls back to local JSONL file
// A separate flow can replay the file when DB recovers Common Use Cases
Retry Logic
Automatically retry failed HTTP, MQTT, or database operations
Error Logging
Centralized error logging to files, databases, or external services
Alert Notifications
Send Slack, email, or SMS alerts when critical errors occur
Fallback Paths
Route to alternative processing when primary paths fail