{"record":{"id":"6e261db952d6f933","repo":"windmill-labs/windmill","slug":"this-draft-has-a-newer-conflicting-version-on-the","errorCode":null,"errorMessage":"This draft has a newer conflicting version on the server. Resolve it here before opening a session.","messagePattern":"This draft has a newer conflicting version on the server\\. Resolve it here before opening a session\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/sessions/pageDrawerSession.ts","lineNumber":54,"sourceCode":"\t)\n}\n\n// Push the drawer's pending autosave and refuse to leave if it did not land: `flush`\n// reports a failed or conflicting POST through its state rather than by throwing, so\n// routing regardless would open the preview on the server's older draft while the drawer\n// the user is looking at still holds the edit. The flush is the explicit kind, saving even\n// with auto-save off: asking for a session is asking for the edit to come along.\nasync function flushOrRefuse(query: Parameters<typeof UserDraftDbSyncer.flush>[0]): Promise<void> {\n\t// Before the save, not after: text that does not parse never reached the draft, so\n\t// leaving now would open the session on the last value that did and drop the buffer\n\t// with the drawer — and saving first would write that stale value on the way to\n\t// refusing. The editors were materialised before this call, so the check is current.\n\tif (anyEditorUnparseable()) {\n\t\tthrow new Error('This page has changes that are not valid JSON. Fix them first.')\n\t}\n\tawait UserDraftDbSyncer.flush(query)\n\tif (UserDraftDbSyncer.getConflict(query).conflict) {\n\t\tthrow new Error(\n\t\t\t'This draft has a newer conflicting version on the server. Resolve it here before opening a session.'\n\t\t)\n\t}\n\tconst { state, failureMessage } = UserDraftDbSyncer.getState(query)\n\tif (state === 'failed') {\n\t\tthrow new Error(\n\t\t\t`Saving the latest draft failed (${failureMessage ?? 'unknown error'}). Retry before opening a session.`\n\t\t)\n\t}\n}\n\n// How each page addresses a row in its hash. Resources route theirs through an extra\n// segment; every other page names the path directly.\nconst drawerHashFor = (pagePath: string, itemPath: string) =>\n\tpagePath === RESOURCES_PATH ? `/resource/${itemPath}` : itemPath\n\n/**\n * Deep-link the row whose drawer just opened, so the location says what is on screen — a","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/sessions/pageDrawerSession.ts#L36-L72","documentation":"After flushing the local draft, flushOrRefuse checks UserDraftDbSyncer for a conflict. If the server holds a newer version of the draft than the one just saved, it refuses to open the session so the user resolves the divergence in the editor first, preventing the session from starting on a stale draft.","triggerScenarios":"flushOrRefuse(query) where getConflict(query).conflict is true — i.e. another tab/device or a concurrent edit wrote a newer draft version on the server while this page was open.","commonSituations":"The same draft edited in two browser tabs; a teammate edited the shared resource draft; the page was left open overnight while background sync updated the server copy.","solutions":["Resolve the conflict in the editor UI (reload server version and reapply or discard local changes), then retry","Reload the page to pick up the newer server draft before opening the session","Coordinate with whoever edited the draft concurrently"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const { conflict } = UserDraftDbSyncer.getConflict(query)\nif (conflict) return; // resolve before opening a session","typeGuard":null,"tryCatchPattern":"try { await openSession(query) } catch (e) { if (/conflicting version/.test(String(e))) promptConflictResolution(); else throw e }","preventionTips":["Avoid editing the same draft in multiple tabs","Reload the draft before long editing sessions","Resolve conflict banners promptly instead of ignoring them"],"tags":["drafts","conflict","concurrency","sessions"],"backgroundTag":"draft-conflict","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}