{"record":{"id":"662ad26dae7712c9","repo":"jgraph/drawio-desktop","slug":"bad-arg-fileobject","errorCode":null,"errorMessage":"bad arg: fileObject","messagePattern":"bad arg: fileObject","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/electron.js","lineNumber":3841,"sourceCode":"\t\t\tfonts = [...new Set(fonts)].sort(\n\t\t\t\t(a, b) => a.localeCompare(b));\n\t\t\tresolve(fonts);\n\t\t});\n\t});\n}\n\nipcMain.on(\"rendererReq\", async (event, args) =>\n{\n\tif (!validateSender(event.senderFrame)) return null;\n\n\ttry\n\t{\n\t\tlet ret = null;\n\n\t\tswitch(args.action)\n\t\t{\n\t\tcase 'saveFile':\n\t\t\tif (args.fileObject == null) throw new Error('bad arg: fileObject');\n\t\t\treqStr(args.fileObject.path, 'fileObject.path');\n\t\t\tret = await saveFile(args.fileObject, args.data, args.origStat, args.overwrite, args.defEnc);\n\t\t\tbreak;\n\t\tcase 'writeFile':\n\t\t\treqStr(args.path, 'path');\n\t\t\tret = await writeFile(args.path, args.data, args.enc);\n\t\t\tbreak;\n\t\tcase 'saveDraft':\n\t\t\tif (args.fileObject == null) throw new Error('bad arg: fileObject');\n\t\t\treqStr(args.fileObject.path, 'fileObject.path');\n\t\t\tret = await saveDraft(args.fileObject, args.data);\n\t\t\tbreak;\n\t\tcase 'getFileDrafts':\n\t\t\tif (args.fileObject == null) throw new Error('bad arg: fileObject');\n\t\t\treqStr(args.fileObject.path, 'fileObject.path');\n\t\t\tret = await getFileDrafts(args.fileObject);\n\t\t\tbreak;\n\t\tcase 'getBkpFile':","sourceCodeStart":3823,"sourceCodeEnd":3859,"githubUrl":"https://github.com/jgraph/drawio-desktop/blob/403a2cb79f431db13a395f033b67eeebc1631754/src/main/electron.js#L3823-L3859","documentation":"In the rendererReq switch (src/main/electron.js:3840-3844), the 'saveFile' case throws 'bad arg: fileObject' when args.fileObject is null/undefined before reqStr validates fileObject.path. This is the IPC entry guard for saveFile.","triggerScenarios":"Renderer sends {action: 'saveFile', fileObject: null, data} or omits fileObject entirely.","commonSituations":"Save triggered before a file was opened/created (no fileObject yet); a refactor dropped the fileObject from the payload; structured-clone dropped a non-cloneable fileObject.","solutions":["Ensure the renderer constructs a fileObject ({path, encoding?}) before dispatching saveFile.","Gate the save button/menu on fileObject presence.","Log args at dispatch to confirm fileObject was set."],"exampleFix":"// before\nif (xml) electron.request({action: 'saveFile', fileObject: currentFile, data: xml});\n\n// after\nif (xml && currentFile && currentFile.path) {\n  electron.request({action: 'saveFile', fileObject: currentFile, data: xml});\n}","handlingStrategy":"type-guard","validationCode":"const hasFileObject = (args) => args && args.fileObject != null && typeof args.fileObject === 'object';\nif (!hasFileObject(args)) throw new TypeError('fileObject required');","typeGuard":"function hasFileObject(args) {\n\treturn args != null && args.fileObject != null && typeof args.fileObject === 'object';\n}","tryCatchPattern":"try { await electron.request({action: 'saveFile', fileObject, data}); }\ncatch (e) {\n\tif (e.message === 'bad arg: fileObject') { /* prompt user to Save As first */ return; }\n\tthrow e;\n}","preventionTips":["Disable Save until a fileObject exists (after open or Save As).","Centralise fileObject construction in one renderer module.","Log the IPC payload shape when this fires to catch regressions."],"tags":["ipc","validation","save","argument"],"backgroundTag":null,"analyzedSha":"403a2cb79f431db13a395f033b67eeebc1631754","analyzedAt":"2026-08-13T00:15:02.468Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}