{"record":{"id":"5f7398c7fb3065a1","repo":"louislam/dockge","slug":"stack-name-and-service-name-must-be-strings","errorCode":null,"errorMessage":"Stack name and service name must be strings","messagePattern":"Stack name and service name must be strings","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"backend/agent-socket-handlers/docker-socket-handler.ts","lineNumber":265,"sourceCode":"\n                const dockerStats = Object.fromEntries(await server.getDockerStats());\n                callbackResult({\n                    ok: true,\n                    dockerStats,\n                }, callback);\n                server.sendStackList();\n            } catch (e) {\n                callbackError(e, callback);\n            }\n        });\n\n        // Start a service\n        agentSocket.on(\"startService\", async (stackName: unknown, serviceName: unknown, callback) => {\n            try {\n                checkLogin(socket);\n\n                if (typeof (stackName) !== \"string\" || typeof (serviceName) !== \"string\") {\n                    throw new ValidationError(\"Stack name and service name must be strings\");\n                }\n\n                const stack = await Stack.getStack(server, stackName);\n                await stack.startService(socket, serviceName);\n                stack.joinCombinedTerminal(socket); // Ensure the combined terminal is joined\n                callbackResult({\n                    ok: true,\n                    msg: \"Service \" + serviceName + \" started\"\n                }, callback);\n                server.sendStackList();\n            } catch (e) {\n                callbackError(e, callback);\n            }\n        });\n\n        // Stop a service\n        agentSocket.on(\"stopService\", async (stackName: unknown, serviceName: unknown, callback) => {\n            try {","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/louislam/dockge/blob/f809ae192b571944ad773e9866d3e67064ae8043/backend/agent-socket-handlers/docker-socket-handler.ts#L247-L283","documentation":"ValidationError thrown by the 'startService' handler when either stackName or serviceName is not a string. Both values are interpolated into Docker service commands (docker compose start <service> in stack <name>), so both are strictly type-checked before use.","triggerScenarios":"socket.emit('startService', stackName, serviceName) with either argument null/undefined/non-string — e.g. serviceName undefined because the service row was not hydrated, or stackName an object.","commonSituations":"Clicking start on a service whose name prop is missing; passing the wrong argument order (serviceName first); scripts iterating services with undefined entries.","solutions":["Ensure both arguments are strings in the emit call and in the correct order (stackName, serviceName)","Validate before emitting: if (typeof s === 'string' && typeof svc === 'string') socket.emit(...)","Fix the component so serviceName is always defined for rendered rows","Log the payload values when the error occurs to find which one is malformed"],"exampleFix":"// before\nsocket.emit(\"startService\", stack, service?.name, cb);\n// after\nif (typeof service?.name === \"string\") socket.emit(\"startService\", stack.name, service.name, cb);","handlingStrategy":"validation","validationCode":"function assertStartServiceArgs(stackName: unknown, serviceName: unknown): asserts stackName is string {\n  if (typeof stackName !== \"string\" || typeof serviceName !== \"string\") {\n    throw new TypeError(\"startService requires string stackName and serviceName\");\n  }\n}","typeGuard":"const bothStrings = (a: unknown, b: unknown): a is string => typeof a === \"string\" && typeof b === \"string\";","tryCatchPattern":"try {\n  assertStartServiceArgs(stackName, serviceName);\n  socket.emit(\"startService\", stackName, serviceName, (res) => {\n    if (!res.ok) console.error(\"startService failed:\", res.msg);\n  });\n} catch (e) { console.error(e); }","preventionTips":["Keep argument order consistent across start/stop/restart handlers","Render service actions only when the service name is hydrated","Centralize service action emits in one validated helper"],"tags":["validation","socket-io","typescript","type-error"],"backgroundTag":"invalid-argument-type","analyzedSha":"f809ae192b571944ad773e9866d3e67064ae8043","analyzedAt":"2026-08-31T19:13:50.919Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}