{"record":{"id":"e1f9f1d95564d08c","repo":"louislam/dockge","slug":"dockerruncommand-must-be-a-string","errorCode":null,"errorMessage":"dockerRunCommand must be a string","messagePattern":"dockerRunCommand must be a string","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"backend/socket-handlers/main-socket-handler.ts","lineNumber":329,"sourceCode":"        // Disconnect all other socket clients of the user\n        socket.on(\"disconnectOtherSocketClients\", async () => {\n            try {\n                checkLogin(socket);\n                server.disconnectAllSocketClients(socket.userID, socket.id);\n            } catch (e) {\n                if (e instanceof Error) {\n                    log.warn(\"disconnectOtherSocketClients\", e.message);\n                }\n            }\n        });\n\n        // composerize\n        socket.on(\"composerize\", async (dockerRunCommand : unknown, callback) => {\n            try {\n                checkLogin(socket);\n\n                if (typeof(dockerRunCommand) !== \"string\") {\n                    throw new ValidationError(\"dockerRunCommand must be a string\");\n                }\n\n                // Option: 'latest' | 'v2x' | 'v3x'\n                let composeTemplate = composerize(dockerRunCommand, \"\", \"latest\");\n\n                // Remove the first line \"name: <your project name>\"\n                composeTemplate = composeTemplate.split(\"\\n\").slice(1).join(\"\\n\");\n\n                callback({\n                    ok: true,\n                    composeTemplate,\n                });\n            } catch (e) {\n                callbackError(e, callback);\n            }\n        });\n    }\n","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/louislam/dockge/blob/f809ae192b571944ad773e9866d3e67064ae8043/backend/socket-handlers/main-socket-handler.ts#L311-L347","documentation":"The 'composerize' socket event converts a docker run command into docker-compose YAML. The dockerRunCommand argument is typed unknown, so the handler first performs a strict typeof check and throws a ValidationError if it is not a string. This guarantees composerize() only ever receives string input.","triggerScenarios":"Emitting 'composerize' with a non-string first argument: null, undefined, an object like { cmd: '...' }, an array of args, or a number.","commonSituations":"Frontend binding an unset input model (undefined) to the event; scripts passing an array of CLI tokens instead of one joined string; JSON payloads where the value arrived as an object.","solutions":["Pass the docker run command as a single string, e.g. 'docker run -d -p 8080:80 nginx'.","Join array tokens with spaces before emitting: args.join(' ').","Coerce/guard the value: if (typeof cmd === 'string') emit(...)."],"exampleFix":"// before\nsocket.emit('composerize', ['-d', '-p', '8080:80', 'nginx'], cb);\n// after\nsocket.emit('composerize', 'docker run -d -p 8080:80 nginx', cb);","handlingStrategy":"type-guard","validationCode":"function isDockerRunCommand(v) {\n    return typeof v === 'string' && v.trim().startsWith('docker run');\n}","typeGuard":"function isString(v) { return typeof v === 'string'; }","tryCatchPattern":"try {\n    socket.emit('composerize', cmd, (res) => {\n        if (!res.ok) throw new TypeError('dockerRunCommand must be a string');\n    });\n} catch (e) {\n    if (e instanceof TypeError) showInputError(e.message);\n}","preventionTips":["Always pass a single joined string, never arrays of CLI tokens","Coerce template bindings to string with String(cmd ?? '')","Check the input box actually has a value before emitting"],"tags":["validation","typescript","input-validation","docker"],"backgroundTag":"wrong-argument-type","analyzedSha":"f809ae192b571944ad773e9866d3e67064ae8043","analyzedAt":"2026-08-31T19:13:50.919Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}