{ "name": "n8n Silent Workflow Check", "nodes": [ { "parameters": { "content": "## Silent workflow check\n\nSet baseUrl and staleHours in Configuration. Select the same Header Auth credential on both HTTP nodes: X-N8N-API-KEY with your n8n API key. The schedule starts at 08:00 UTC.\n\nEach run reads at most 250 workflows and 250 executions. Inspect the returned findings and page-limit flags; an absent execution may be outside this window. No alert is sent. An outage of the hosting n8n instance also stops this schedule.", "height": 620, "width": 460 }, "id": "8f1c0a10-0000-4000-8000-000000000001", "name": "Read me", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [ -460, -120 ] }, { "parameters": { "rule": { "interval": [ { "field": "cronExpression", "expression": "0 8 * * *" } ] } }, "id": "8f1c0a10-0000-4000-8000-000000000002", "name": "Every morning", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [ 40, 100 ] }, { "parameters": { "assignments": { "assignments": [ { "id": "a1", "name": "baseUrl", "value": "https://n8n.example.com", "type": "string" }, { "id": "a2", "name": "staleHours", "value": 26, "type": "number" } ] }, "options": {} }, "id": "8f1c0a10-0000-4000-8000-000000000003", "name": "Configuration", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 260, 100 ] }, { "parameters": { "url": "={{ $json.baseUrl }}/api/v1/workflows?limit=250", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "options": {} }, "id": "8f1c0a10-0000-4000-8000-000000000004", "name": "Get workflows", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 480, 100 ] }, { "parameters": { "url": "={{ $('Configuration').first().json.baseUrl }}/api/v1/executions?limit=250", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "options": {} }, "id": "8f1c0a10-0000-4000-8000-000000000005", "name": "Get executions", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 700, 100 ] }, { "parameters": { "mode": "runOnceForAllItems", "jsCode": "function findSilent({workflows, executions, staleHours, now, workflowCursor, executionCursor}) {\n if (!Array.isArray(workflows) || !Array.isArray(executions)) throw new Error('Workflow and execution pages must be arrays');\n if (!Number.isFinite(staleHours) || staleHours <= 0) throw new Error('staleHours must be a positive number');\n const timestamp = new Date(now).getTime();\n if (!Number.isFinite(timestamp)) throw new Error('now must be a valid timestamp');\n const active = workflows.filter(workflow => workflow.active && !workflow.isArchived);\n const latest = new Map();\n for (const execution of executions) {\n const id = String(execution.workflowId);\n const started = new Date(execution.startedAt || execution.createdAt).getTime();\n if (!Number.isFinite(started)) continue;\n if (!latest.has(id) || started > latest.get(id)) latest.set(id, started);\n }\n const threshold = timestamp - staleHours * 3600000;\n const findings = [];\n for (const workflow of active) {\n const last = latest.get(String(workflow.id));\n if (last === undefined) findings.push({ workflow: workflow.name, workflowId: workflow.id, lastRun: null, hoursSilent: null, note: 'no execution in the window' });\n else if (last < threshold) findings.push({ workflow: workflow.name, workflowId: workflow.id, lastRun: new Date(last).toISOString(), hoursSilent: Math.round((timestamp - last) / 3600000), note: 'active but stalled' });\n }\n return { silent: findings.length, activeChecked: active.length, findings, workflowPageLimited: Boolean(workflowCursor), executionPageLimited: Boolean(executionCursor) };\n}\n\nconst workflowPage=$('Get workflows').first().json;\nconst executionPage=$('Get executions').first().json;\nreturn [{json:findSilent({workflows:workflowPage.data ?? [],executions:executionPage.data ?? [],staleHours:Number($('Configuration').first().json.staleHours),now:$now.toISO(),workflowCursor:workflowPage.nextCursor ?? null,executionCursor:executionPage.nextCursor ?? null})}];\n" }, "id": "8f1c0a10-0000-4000-8000-000000000006", "name": "Find silent workflows", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 920, 100 ] } ], "connections": { "Every morning": { "main": [ [ { "node": "Configuration", "type": "main", "index": 0 } ] ] }, "Configuration": { "main": [ [ { "node": "Get workflows", "type": "main", "index": 0 } ] ] }, "Get workflows": { "main": [ [ { "node": "Get executions", "type": "main", "index": 0 } ] ] }, "Get executions": { "main": [ [ { "node": "Find silent workflows", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1", "timezone": "UTC" }, "pinData": {}, "active": false }