From 0ba573a24d0ddf12ef5406e5395937acfc8e59cc Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Sun, 8 Feb 2026 09:54:15 -0500 Subject: [PATCH] feat(10.1-08): add statusCode handling to container action result formatters - Add HTTP 304 detection for 'already in desired state' (success: true) - Add HTTP 404 detection for 'container not found' (success: false) - Add HTTP 500+ detection for server errors (success: false) - Apply to Format Stop/Start/Restart Result nodes - StatusCode checks run before existing message-based fallback logic --- n8n-actions.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/n8n-actions.json b/n8n-actions.json index 26ce6fb..a6c7ff2 100644 --- a/n8n-actions.json +++ b/n8n-actions.json @@ -247,7 +247,7 @@ }, { "parameters": { - "jsCode": "// Format start action result\n// Get data from Route Action (works for both direct and resolved ID paths)\nconst routeData = $('Route Action').item.json;\nconst containerId = routeData.containerId;\nconst containerName = routeData.containerName;\nconst action = routeData.action;\nconst chatId = routeData.chatId;\nconst messageId = routeData.messageId;\nconst responseMode = routeData.responseMode;\n\n// Docker API returns 204 No Content on success (empty response body)\n// Error responses contain 'message' field\nconst response = $input.item.json || {};\nconst hasError = response.message || response.error || false;\n\n// Success = no error message in response (empty {} means 204 success)\nconst success = !hasError;\n\nlet message;\nif (success) {\n message = `\\u25B6\\uFE0F ${containerName} started successfully`;\n} else {\n message = `\\u274C Failed to start ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" + "jsCode": "// Format start action result\n// Get data from Route Action (works for both direct and resolved ID paths)\nconst routeData = $('Route Action').item.json;\nconst containerId = routeData.containerId;\nconst containerName = routeData.containerName;\nconst action = routeData.action;\nconst chatId = routeData.chatId;\nconst messageId = routeData.messageId;\nconst responseMode = routeData.responseMode;\n\nconst response = $input.item.json || {};\n\n// Check HTTP status codes first (Docker API with onError:continueRegularOutput)\nif (response.statusCode) {\n if (response.statusCode === 304) {\n // Already in desired state\n return {\n json: {\n success: true,\n message: `\\u2705 ${containerName} is already started`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n } else if (response.statusCode === 404) {\n return {\n json: {\n success: false,\n message: `\\u274C Container ${containerName} not found`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n } else if (response.statusCode >= 500) {\n return {\n json: {\n success: false,\n message: `\\u274C Server error starting ${containerName}: ${response.statusMessage || 'Unknown error'}`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n }\n}\n\n// Docker API returns 204 No Content on success (empty response body)\n// Error responses contain 'message' field\nconst hasError = response.message || response.error || false;\n\n// Success = no error message in response (empty {} means 204 success)\nconst success = !hasError;\n\nlet message;\nif (success) {\n message = `\\u25B6\\uFE0F ${containerName} started successfully`;\n} else {\n message = `\\u274C Failed to start ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" }, "id": "code-format-start-result", "name": "Format Start Result", @@ -260,7 +260,7 @@ }, { "parameters": { - "jsCode": "// Format stop action result\n// Get data from Route Action (works for both direct and resolved ID paths)\nconst routeData = $('Route Action').item.json;\nconst containerId = routeData.containerId;\nconst containerName = routeData.containerName;\nconst action = routeData.action;\nconst chatId = routeData.chatId;\nconst messageId = routeData.messageId;\nconst responseMode = routeData.responseMode;\n\n// Docker API returns 204 No Content on success (empty response body)\n// Error responses contain 'message' field\nconst response = $input.item.json || {};\nconst hasError = response.message || response.error || false;\n\n// Success = no error message in response (empty {} means 204 success)\nconst success = !hasError;\n\nlet message;\nif (success) {\n message = `\\u23F9\\uFE0F ${containerName} stopped`;\n} else {\n message = `\\u274C Failed to stop ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" + "jsCode": "// Format stop action result\n// Get data from Route Action (works for both direct and resolved ID paths)\nconst routeData = $('Route Action').item.json;\nconst containerId = routeData.containerId;\nconst containerName = routeData.containerName;\nconst action = routeData.action;\nconst chatId = routeData.chatId;\nconst messageId = routeData.messageId;\nconst responseMode = routeData.responseMode;\n\nconst response = $input.item.json || {};\n\n// Check HTTP status codes first (Docker API with onError:continueRegularOutput)\nif (response.statusCode) {\n if (response.statusCode === 304) {\n // Already in desired state\n return {\n json: {\n success: true,\n message: `\\u2705 ${containerName} is already stopped`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n } else if (response.statusCode === 404) {\n return {\n json: {\n success: false,\n message: `\\u274C Container ${containerName} not found`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n } else if (response.statusCode >= 500) {\n return {\n json: {\n success: false,\n message: `\\u274C Server error stopping ${containerName}: ${response.statusMessage || 'Unknown error'}`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n }\n}\n\n// Docker API returns 204 No Content on success (empty response body)\n// Error responses contain 'message' field\nconst hasError = response.message || response.error || false;\n\n// Success = no error message in response (empty {} means 204 success)\nconst success = !hasError;\n\nlet message;\nif (success) {\n message = `\\u23F9\\uFE0F ${containerName} stopped`;\n} else {\n message = `\\u274C Failed to stop ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" }, "id": "code-format-stop-result", "name": "Format Stop Result", @@ -273,7 +273,7 @@ }, { "parameters": { - "jsCode": "// Format restart action result\n// Get data from Route Action (works for both direct and resolved ID paths)\nconst routeData = $('Route Action').item.json;\nconst containerId = routeData.containerId;\nconst containerName = routeData.containerName;\nconst action = routeData.action;\nconst chatId = routeData.chatId;\nconst messageId = routeData.messageId;\nconst responseMode = routeData.responseMode;\n\n// Docker API returns 204 No Content on success (empty response body)\n// Error responses contain 'message' field\nconst response = $input.item.json || {};\nconst hasError = response.message || response.error || false;\n\n// Success = no error message in response (empty {} means 204 success)\nconst success = !hasError;\n\nlet message;\nif (success) {\n message = `\\u{1F504} ${containerName} restarted`;\n} else {\n message = `\\u274C Failed to restart ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" + "jsCode": "// Format restart action result\n// Get data from Route Action (works for both direct and resolved ID paths)\nconst routeData = $('Route Action').item.json;\nconst containerId = routeData.containerId;\nconst containerName = routeData.containerName;\nconst action = routeData.action;\nconst chatId = routeData.chatId;\nconst messageId = routeData.messageId;\nconst responseMode = routeData.responseMode;\n\nconst response = $input.item.json || {};\n\n// Check HTTP status codes first (Docker API with onError:continueRegularOutput)\nif (response.statusCode) {\n if (response.statusCode === 304) {\n // Already in desired state (running)\n return {\n json: {\n success: true,\n message: `\\u2705 ${containerName} is already started`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n } else if (response.statusCode === 404) {\n return {\n json: {\n success: false,\n message: `\\u274C Container ${containerName} not found`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n } else if (response.statusCode >= 500) {\n return {\n json: {\n success: false,\n message: `\\u274C Server error restarting ${containerName}: ${response.statusMessage || 'Unknown error'}`,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n };\n }\n}\n\n// Docker API returns 204 No Content on success (empty response body)\n// Error responses contain 'message' field\nconst hasError = response.message || response.error || false;\n\n// Success = no error message in response (empty {} means 204 success)\nconst success = !hasError;\n\nlet message;\nif (success) {\n message = `\\u{1F504} ${containerName} restarted`;\n} else {\n message = `\\u274C Failed to restart ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" }, "id": "code-format-restart-result", "name": "Format Restart Result",