{"record":{"id":"4d9fcbf87ca96a59","repo":"jgraph/drawio-desktop","slug":"conflict","errorCode":null,"errorMessage":"conflict","messagePattern":"conflict","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/electron.js","lineNumber":3560,"sourceCode":"\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn await writeFile();\n\t};\n\t\n\tif (overwrite)\n\t{\n\t\treturn await doSaveFile(true);\n\t}\n\telse\n\t{\n\t\tlet stat = fs.existsSync(fileObject.path)?\n\t\t\t\t\tawait fsProm.stat(fileObject.path) : null;\n\n\t\tif (stat && isConflict(origStat, stat))\n\t\t{\n\t\t\tthrow new Error('conflict');\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn await doSaveFile(stat == null);\n\t\t}\n\t}\n};\n\nasync function writeFile(filePath, data, enc)\n{\n\tif (!checkFileContent(data, enc))\n\t{\n\t\tthrow new Error('Invalid file data');\n\t}\n\n\tawait assertWritablePath(filePath);\n\n\tlet fh;","sourceCodeStart":3542,"sourceCodeEnd":3578,"githubUrl":"https://github.com/jgraph/drawio-desktop/blob/403a2cb79f431db13a395f033b67eeebc1631754/src/main/electron.js#L3542-L3578","documentation":"saveFile's non-overwrite path (src/main/electron.js:3553-3561) stats the target file and compares its mtimeMs to origStat (via isConflict, line 3168-3171). If they differ, another process edited the file since drawio last read it, so saving would clobber someone else's work — it throws 'conflict' instead.","triggerScenarios":"User A opens a shared file, user B saves it, then user A triggers save without overwrite=true; a cloud-sync client rewrote the file (touching mtime) between open and save; an external editor auto-formatted it.","commonSituations":"Network shares, Dropbox/OneDrive/Google Drive folders, git checkouts touched by another tool, or two drawio windows editing the same file.","solutions":["Prompt the user and re-save with overwrite=true (args.overwrite) after they confirm.","Re-read the file and merge or pick a winner before saving.","Avoid editing shared/cloud-synced diagrams with two writers; close other editors first."],"exampleFix":"// before\nsaveFile(fileObject, data, origStat, false);\n\n// after\ntry { await saveFile(fileObject, data, origStat, false); }\ncatch (e) {\n  if (e.message === 'conflict' && await confirmOverwrite()) {\n    await saveFile(fileObject, data, await fs.stat(fileObject.path), true);\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"async function fileUnchangedSince(origStat, p) {\n\tif (!origStat || !fs.existsSync(p)) return true;\n\tconst s = await fsProm.stat(p);\n\treturn s.mtimeMs === origStat.mtimeMs;\n}","typeGuard":null,"tryCatchPattern":"try { await saveFile(fileObject, data, origStat, false); }\ncatch (e) {\n\tif (e.message === 'conflict' && await userConfirmsOverwrite()) {\n\t\tconst fresh = await fsProm.stat(fileObject.path);\n\t\tawait saveFile(fileObject, data, fresh, true);\n\t} else throw e;\n}","preventionTips":["For shared/cloud-synced files, prefer overwrite=true after explicit user confirmation.","Refresh origStat after every save so subsequent saves compare against the latest mtime.","Warn users when two editors have the same file open."],"tags":["save","conflict","mtime","concurrency"],"backgroundTag":null,"analyzedSha":"403a2cb79f431db13a395f033b67eeebc1631754","analyzedAt":"2026-08-13T00:15:02.468Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}