{"record":{"id":"a22bf5b9ea2c8b62","repo":"louislam/dockge","slug":"data-must-be-an-object","errorCode":null,"errorMessage":"Data must be an object","messagePattern":"Data must be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"backend/socket-handlers/manage-agent-socket-handler.ts","lineNumber":17,"sourceCode":"import { SocketHandler } from \"../socket-handler.js\";\nimport { DockgeServer } from \"../dockge-server\";\nimport { log } from \"../log\";\nimport { callbackError, callbackResult, checkLogin, DockgeSocket } from \"../util-server\";\nimport { LooseObject } from \"../../common/util-common\";\n\nexport class ManageAgentSocketHandler extends SocketHandler {\n\n    create(socket : DockgeSocket, server : DockgeServer) {\n        // addAgent\n        socket.on(\"addAgent\", async (requestData : unknown, callback : unknown) => {\n            try {\n                log.debug(\"manage-agent-socket-handler\", \"addAgent\");\n                checkLogin(socket);\n\n                if (typeof(requestData) !== \"object\") {\n                    throw new Error(\"Data must be an object\");\n                }\n\n                let data = requestData as LooseObject;\n                let manager = socket.instanceManager;\n                await manager.test(data.url, data.username, data.password);\n                await manager.add(data.url, data.username, data.password, data.name);\n\n                // connect to the agent\n                manager.connect(data.url, data.username, data.password);\n\n                // Refresh another sockets\n                // It is a bit difficult to control another browser sessions to connect/disconnect agents, so force them to refresh the page will be easier.\n                server.disconnectAllSocketClients(undefined, socket.id);\n                manager.sendAgentList();\n\n                callbackResult({\n                    ok: true,\n                    msg: \"agentAddedSuccessfully\",","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/louislam/dockge/blob/f809ae192b571944ad773e9866d3e67064ae8043/backend/socket-handlers/manage-agent-socket-handler.ts#L1-L35","documentation":"The 'addAgent' socket event expects a single requestData object carrying url, username, password, and name. Because the argument is unknown, the handler checks typeof(requestData) === 'object' and throws this Error otherwise, preventing destructure/type errors and undefined-field calls into instanceManager.test/add.","triggerScenarios":"Emitting 'addAgent' with null (typeof null === 'object' but the check is per-source; a null/undefined/primitive such as a bare URL string or number) instead of a request object.","commonSituations":"Scripts emitting only the URL string instead of the object; unserialized payload arriving undefined; frontend sending separate positional args rather than one object.","solutions":["Emit a single object: { url, username, password, name }.","Guard with typeof data === 'object' && data !== null before emitting.","Ensure all fields (url, username, password, name) are populated strings."],"exampleFix":"// before\nsocket.emit('addAgent', 'http://agent:5001', cb);\n// after\nsocket.emit('addAgent', { url: 'http://agent:5001', username: 'user', password: 'pass1', name: 'agent1' }, cb);","handlingStrategy":"type-guard","validationCode":"function isAddAgentPayload(v) {\n    return typeof v === 'object' && v !== null\n        && typeof v.url === 'string'\n        && typeof v.username === 'string'\n        && typeof v.password === 'string';\n}","typeGuard":"function isObject(v) { return typeof v === 'object' && v !== null; }","tryCatchPattern":"if (!isAddAgentPayload(data)) {\n    throw new Error('Data must be an object');\n}\nsocket.emit('addAgent', data, cb);","preventionTips":["Always emit one object containing url/username/password/name","Serialize payloads explicitly rather than passing positional args","Validate object shape (not just typeof) before emitting"],"tags":["validation","input-validation","typescript","agents"],"backgroundTag":"wrong-argument-type","analyzedSha":"f809ae192b571944ad773e9866d3e67064ae8043","analyzedAt":"2026-08-31T19:13:50.919Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}