{"record":{"id":"6eb796e2d9305359","repo":"n8n-io/n8n","slug":"423","errorCode":"423","errorMessage":"Cannot modify workflow while it is being edited by a user in the editor.","messagePattern":"Cannot modify workflow while it is being edited by a user in the editor\\.","errorType":"http","errorClass":"LockedError","httpStatus":423,"severity":"warning","filePath":"packages/cli/src/collaboration/collaboration.service.ts","lineNumber":364,"sourceCode":"\t */\n\tasync getWriteLock(\n\t\tuserId: User['id'],\n\t\tworkflowId: Workflow['id'],\n\t): Promise<{ clientId: string; userId: string } | null> {\n\t\tif (!(await this.accessService.hasReadAccess(userId, workflowId))) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn await this.state.getWriteLock(workflowId);\n\t}\n\n\t/**\n\t * Throws if any user currently holds the write lock for the given workflow.\n\t */\n\tasync ensureWorkflowEditable(workflowId: Workflow['id']): Promise<void> {\n\t\tconst lock = await this.state.getWriteLock(workflowId);\n\t\tif (lock) {\n\t\t\tthrow new LockedError(\n\t\t\t\t'Cannot modify workflow while it is being edited by a user in the editor.',\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Validates that if a write lock exists for a workflow, the requesting client holds it.\n\t * Throws ConflictError (409) if same user but different tab holds the lock.\n\t * Throws LockedError (423) if different user holds the lock.\n\t */\n\tasync validateWriteLock(\n\t\tuserId: User['id'],\n\t\tclientId: string | undefined,\n\t\tworkflowId: Workflow['id'],\n\t\taction: string,\n\t): Promise<void> {\n\t\tif (!clientId) {\n\t\t\treturn;","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/collaboration/collaboration.service.ts#L346-L382","documentation":"CollaborationService.ensureWorkflowEditable throws LockedError (423) when any user currently holds the write lock for the workflow. Used to block mutations (save, activate, delete) while someone is editing in the UI.","triggerScenarios":"A mutating API call hits ensureWorkflowEditable and state.getWriteLock(workflowId) returns a non-null lock — another user (or the same user in another tab) has the editor open in write mode.","commonSituations":"Two users editing the same workflow; a user closed the tab without releasing the lock (lock TTL still active); automation/CI trying to save a workflow a user has open.","solutions":["Have the locking user close the editor tab to release the lock, then retry.","Wait for the lock TTL to expire if the holder is idle.","Use the collaboration 'take over' flow if available, or coordinate edit windows."],"exampleFix":"n/a","handlingStrategy":"try-catch","validationCode":"// Before mutating, check editability\nconst lock = await collaborationService.state.getWriteLock(workflowId);\nif (lock) { /* someone holds it: surface 423 to caller */ }","typeGuard":"function isLockedError(error: unknown): boolean {\n  return error instanceof Error && /Cannot modify workflow/.test(error.message);\n}","tryCatchPattern":"try {\n  await collaborationService.ensureWorkflowEditable(workflowId);\n} catch (e) {\n  if (isLockedError(e)) { /* return 423, ask user to retry later */ }\n  else throw e;\n}","preventionTips":["Close editor tabs to release locks before automating workflow changes.","Use dedicated service accounts for CI to avoid colliding with users.","Honor lock TTLs and retry with backoff on 423."],"tags":["collaboration","locking","workflow","http-423"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}