{"record":{"id":"42715e54420673e4","repo":"windmill-labs/windmill","slug":"cannot-deploy-label-the-draft-has-a-conflictin","errorCode":null,"errorMessage":"Cannot deploy ${label}: the draft has a conflicting newer version on the server. Open it in the editor and resolve the conflict first.","messagePattern":"Cannot deploy (.+?): the draft has a conflicting newer version on the server\\. Open it in the editor and resolve the conflict first\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/global/core.ts","lineNumber":7227,"sourceCode":"\n\ttoolCallbacks.setToolStatus(toolId, {\n\t\tcontent: `Found ${totalMatchCount} matching changed line${totalMatchCount === 1 ? '' : 's'}`\n\t})\n\treturn out.join('\\n') + unflushedNote\n}\n\n// Flush a draft's pending editor autosave, then verify it actually landed before\n// the caller re-reads the persisted draft. `flush()` resolves even when the save\n// recorded a conflict (server has a newer version) or failed (network/5xx) — it\n// does not throw — so without this check a deploy could publish a stale/conflicting\n// draft. Abort with a clear message instead.\nasync function flushDraftOrThrow(\n\tquery: Parameters<typeof UserDraftDbSyncer.flush>[0],\n\tlabel: string\n): Promise<void> {\n\tawait UserDraftDbSyncer.flush(query)\n\tif (UserDraftDbSyncer.getConflict(query).conflict) {\n\t\tthrow new Error(\n\t\t\t`Cannot deploy ${label}: the draft has a conflicting newer version on the server. Open it in the editor and resolve the conflict first.`\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`Cannot deploy ${label}: saving the latest draft failed (${failureMessage ?? 'unknown error'}). Retry once the draft saves.`\n\t\t)\n\t}\n}\n\nasync function deployDraft(\n\targs: {\n\t\ttype: WorkspaceItemType\n\t\tpath: string\n\t\ttrigger_kind?: TriggerKind\n\t\tdeployment_message?: string\n\t\tforce?: boolean","sourceCodeStart":7209,"sourceCodeEnd":7245,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/global/core.ts#L7209-L7245","documentation":"Thrown by flushDraftOrThrow in the Windmill AI chat's global-mode deploy tool. Before deploying an item, the chat flushes its in-browser draft store (UserDraftDbSyncer) to the server; if the syncer reports a conflict — i.e. the server holds a newer version than the local draft was based on — the deploy is aborted rather than silently overwriting someone else's changes. The error tells the user (and the AI agent) to open the item in the Windmill editor and resolve the version conflict manually before deploying again.","triggerScenarios":"Calling the chat's deploy tool (deployDraft → flushDraftOrThrow) when UserDraftDbSyncer.getConflict(query).conflict is true after a flush — i.e. the draft was edited concurrently (by the agent and a human, or in two tabs) so the server version advanced past the draft's base version.","commonSituations":"Two browser tabs editing the same script/flow/app draft; a human editing the item in the editor while the AI copilot is deploying it; a stale draft left open from before a teammate's deploy; agent-driven bulk edits racing with manual edits in one workspace.","solutions":["Open the item in the Windmill editor and resolve the conflict (the editor shows the conflicting server vs draft versions), then retry the deploy.","Discard the local draft to accept the server version, re-apply your intended changes, and deploy again.","If the AI agent hit this, re-run the deploy step after the human resolves the conflict in the editor."],"exampleFix":"// before (deploy fails)\nawait deployDraft({ type: 'script', path: 'f/process', ... })\n// Error: Cannot deploy script \"f/process\": the draft has a conflicting newer version on the server.\n\n// after: open f/process in the editor, resolve the conflict, then retry\nawait deployDraft({ type: 'script', path: 'f/process', ... }) // succeeds","handlingStrategy":"try-catch","validationCode":"import { UserDraftDbSyncer } from '$lib/components/copilot/chat/global/userDraftSyncer'\n// before deploying:\nif (UserDraftDbSyncer.getConflict(query).conflict) {\n  // resolve in editor first; skip the deploy call\n}","typeGuard":"function hasDraftConflict(query) {\n  return UserDraftDbSyncer.getConflict(query).conflict === true\n}","tryCatchPattern":"try {\n  await deployDraft(args)\n} catch (e) {\n  if (/conflicting newer version on the server/.test(e.message)) {\n    // surface 'resolve conflict in editor' guidance to the user\n  } else throw e\n}","preventionTips":["Avoid editing the same draft in the editor while an AI deploy of it is in flight.","Work in a single browser tab per draft to avoid divergent local versions.","Deploy drafts promptly after editing instead of letting them sit stale."],"tags":["draft-sync","conflict","optimistic-locking","deploy"],"backgroundTag":"draft-version-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"}