{"record":{"id":"6002d386d190b7e6","repo":"conductor-oss/conductor","slug":"error-acquiring-lock-when-creating-workflow","errorCode":null,"errorMessage":"Error acquiring lock when creating workflow: {}","messagePattern":"Error acquiring lock when creating workflow: (.+?)","errorType":"exception","errorClass":"TransientException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/com/netflix/conductor/core/execution/WorkflowExecutorOps.java","lineNumber":2639,"sourceCode":"                executionDAOFacade.removeWorkflow(workflowId, false);\n            } catch (Exception rwe) {\n                LOGGER.error(\"Could not remove the workflowId: \" + workflowId, rwe);\n            }\n            throw e;\n        }\n    }\n\n    @Override\n    public WorkflowModel startWorkflowIdempotent(StartWorkflowInput input) {\n        Preconditions.checkArgument(\n                StringUtils.isNotBlank(input.getWorkflowId()),\n                \"workflowId must be present for idempotent workflow start\");\n\n        WorkflowDef workflowDefinition = resolveWorkflowDefinition(input);\n        String workflowId = input.getWorkflowId();\n\n        if (!executionLockService.acquireLock(workflowId)) {\n            throw new TransientException(\"Error acquiring lock when creating workflow: {}\");\n        }\n\n        boolean createAttempted = false;\n        try {\n            try {\n                WorkflowModel existingWorkflow =\n                        executionDAOFacade.getWorkflowModelFromExecutionDAO(workflowId, false);\n                validateIdempotentWorkflowOwnership(input, existingWorkflow);\n                return existingWorkflow;\n            } catch (NotFoundException e) {\n                LOGGER.debug(\n                        \"No existing workflow found in execution store for idempotent start of workflow id {}, proceeding with creation\",\n                        workflowId);\n            }\n\n            WorkflowModel workflow = createWorkflowModel(input, workflowDefinition, workflowId);\n            createAttempted = true;\n            createAndQueueEvaluationWithLock(workflow);","sourceCodeStart":2621,"sourceCodeEnd":2657,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/core/src/main/java/com/netflix/conductor/core/execution/WorkflowExecutorOps.java#L2621-L2657","documentation":"Thrown by startWorkflowIdempotent() when executionLockService.acquireLock(workflowId) returns false. The lock prevents concurrent idempotent starts from racing on the same workflowId — two callers creating the same workflow ID simultaneously would corrupt state. Since lock acquisition failure is temporary (another holder may release), this is a TransientException signaling 'retry later'. Note: the message literal '{}' is an unformatted SLF4J placeholder, not a bug in your input.","triggerScenarios":"Two concurrent startWorkflowIdempotent calls with the same workflowId. The lock service (typically Redis or DynamoDB-based) is unreachable, saturated, or the lock is held by a previous start attempt that has not yet released it. High-throughput idempotent starts under contention.","commonSituations":"Load balancer retrying an idempotent start while the original request is still processing. Lock TTL shorter than workflow creation time, causing the lock to expire and be re-acquired by a different thread while the first is still creating. Redis connectivity issues degrading the lock service.","solutions":["Retry the startWorkflowIdempotent call after a short backoff — the TransientException signals the lock is temporarily unavailable.","Verify the lock service backend (Redis/DynamoDB) is healthy and has capacity.","Check for orphaned locks from crashed nodes — increase lock TTL to exceed typical workflow creation latency.","Reduce concurrent idempotent start calls for the same workflowId by deduplicating at the client layer."],"exampleFix":"// before\nworkflowExecutor.startWorkflowIdempotent(input);\n\n// after\nint maxRetries = 3;\nfor (int i = 0; i <= maxRetries; i++) {\n    try {\n        return workflowExecutor.startWorkflowIdempotent(input);\n    } catch (TransientException e) {\n        if (i == maxRetries) throw e;\n        Thread.sleep(200L * (i + 1));\n    }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    workflowExecutor.startWorkflowIdempotent(input);\n} catch (TransientException e) {\n    // Lock temporarily unavailable — retry with backoff\n    Thread.sleep(retryDelayMs);\n    workflowExecutor.startWorkflowIdempotent(input);\n}","preventionTips":["Wrap idempotent start calls in a retry loop with exponential backoff for TransientException.","Monitor lock service health (Redis/DynamoDB) to detect contention early.","Deduplicate idempotent start requests at the client layer to reduce lock contention."],"tags":["lock","idempotent-start","transient","concurrency","redis"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}