{"record":{"id":"a7cc26d063e7171f","repo":"abpframework/abp","slug":"the-distributed-lock-name-configuration-lockname","errorCode":null,"errorMessage":"The distributed lock name '{configuration.LockName}' is used by more than one background job worker (the default worker uses '{WorkerOptions.DistributedLockName}'). Each worker must have a unique lock name to run independently.","messagePattern":"The distributed lock name '(.+?)' is used by more than one background job worker \\(the default worker uses '(.+?)'\\)\\. Each worker must have a unique lock name to run independently\\.","errorType":"exception","errorClass":"AbpException","httpStatus":null,"severity":"critical","filePath":"framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorkerManager.cs","lineNumber":79,"sourceCode":"\n        foreach (var configuration in WorkerOptions.WorkerConfigurations)\n        {\n            var jobNames = configuration.JobArgsTypes\n                .Select(GetJobName)\n                .Distinct()\n                .ToList();\n\n            var alreadyConfigured = jobNames.Intersect(allDedicatedJobNames).ToList();\n            if (alreadyConfigured.Any())\n            {\n                throw new AbpException(\n                    $\"The following background job(s) are configured for more than one dedicated worker: {string.Join(\", \", alreadyConfigured)}. \" +\n                    $\"Each job type can be handled by only one dedicated worker.\");\n            }\n\n            if (lockNames.Contains(configuration.LockName))\n            {\n                throw new AbpException(\n                    $\"The distributed lock name '{configuration.LockName}' is used by more than one background job worker \" +\n                    $\"(the default worker uses '{WorkerOptions.DistributedLockName}'). Each worker must have a unique lock name to run independently.\");\n            }\n\n            lockNames.Add(configuration.LockName);\n            allDedicatedJobNames.AddRange(jobNames);\n            dedicatedWorkers.Add(new DedicatedWorkerDefinition(configuration.LockName, jobNames));\n        }\n\n        foreach (var dedicatedWorker in dedicatedWorkers)\n        {\n            await StartWorkerAsync(dedicatedWorker.LockName, BackgroundJobNameFilter.Include(dedicatedWorker.JobNames), cancellationToken);\n        }\n\n        // Default worker processes every job that is not handled by a dedicated worker.\n        await StartWorkerAsync(null, BackgroundJobNameFilter.Exclude(allDedicatedJobNames), cancellationToken);\n    }\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorkerManager.cs#L61-L97","documentation":"Thrown during BackgroundJobWorkerManager.StartAsync when a dedicated worker's distributed lock name collides with another worker's lock name or with the default worker's lock name (AbpBackgroundJobWorkerOptions.DistributedLockName, default \"AbpBackgroundJobWorker\"). Each worker needs a unique lock to run independently; a duplicate would cause mutual exclusion to break or serialize the wrong workers. AddDedicatedWorker checks this eagerly, but StartAsync re-validates as a backstop.","triggerScenarios":"Calling AddDedicatedWorker with a lockName that equals AbpBackgroundJobWorkerOptions.DistributedLockName (the default worker's lock). Registering two workers with the same explicit lock name. Changing DistributedLockName at runtime after workers are already registered so it now collides with a dedicated worker's name.","commonSituations":"Explicitly passing \"AbpBackgroundJobWorker\" as the lock name for a dedicated worker, not realizing it is reserved for the default worker. Copy-pasting a dedicated worker registration line and forgetting to change the lock name. Customizing DistributedLockName globally so it collides with an existing dedicated worker lock.","solutions":["Give each dedicated worker a unique lock name that does not match DistributedLockName (e.g. \"AbpBackgroundJobEmailWorker\").","Use the parameterless AddDedicatedWorker<TArgs>() overload, which auto-generates a unique lock name from an MD5 hash of the job type names.","If you customized DistributedLockName, ensure no dedicated worker uses the same string."],"exampleFix":"// before — collides with the default lock name\nConfigure<AbpBackgroundJobWorkerOptions>(opts =>\n{\n    opts.DistributedLockName = \"MyJobWorker\";\n    opts.AddDedicatedWorker<MyJobArgs>(\"MyJobWorker\"); // collision\n});\n\n// after — distinct lock name\nConfigure<AbpBackgroundJobWorkerOptions>(opts =>\n{\n    opts.DistributedLockName = \"MyDefaultJobWorker\";\n    opts.AddDedicatedWorker<MyJobArgs>(\"MyJobDedicatedWorker\");\n});","handlingStrategy":"validation","validationCode":"string lockName = \"MyDedicatedWorker\";\nvar workerOpts = serviceProvider.GetRequiredService<IOptions<AbpBackgroundJobWorkerOptions>>().Value;\nif (lockName == workerOpts.DistributedLockName ||\n    workerOpts.WorkerConfigurations.Any(c => c.LockName == lockName))\n{\n    throw new InvalidOperationException($\"Lock name '{lockName}' is already in use.\");\n}\noptions.AddDedicatedWorker(lockName, jobArgsTypes);","typeGuard":null,"tryCatchPattern":"try { options.AddDedicatedWorker(lockName, jobArgsTypes); }\ncatch (AbpException ex) when (ex.Message.Contains(\"distributed lock name\"))\n{\n    logger.LogError(ex, \"Distributed lock name collision for dedicated worker.\");\n    throw;\n}","preventionTips":["Use the parameterless AddDedicatedWorker<TArgs>() overload to get an auto-generated unique lock name.","Never use the default lock name (\"AbpBackgroundJobWorker\") for a dedicated worker.","Keep a central list of lock names if you assign them explicitly."],"tags":["background-jobs","dedicated-worker","distributed-lock","configuration-conflict","startup"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}