{"record":{"id":"874341169b4c0db9","repo":"OrchardCMS/OrchardCore","slug":"fails-to-acquire-an-auto-setup-lock-for-the-tenant","errorCode":null,"errorMessage":"Fails to acquire an auto setup lock for the tenant: {_setupOptions.ShellName}","messagePattern":"Fails to acquire an auto setup lock for the tenant: (.+?)","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs","lineNumber":101,"sourceCode":"\n    /// <summary>\n    /// The auto setup middleware invoke.\n    /// </summary>\n    /// <param name=\"httpContext\">\n    /// The http context.\n    /// </param>\n    /// <returns>\n    /// The <see cref=\"Task\"/>.\n    /// </returns>\n    public async Task InvokeAsync(HttpContext httpContext)\n    {\n        if (_setupOptions is not null && _shellSettings.IsUninitialized())\n        {\n            // Try to acquire a lock before starting installation, it guaranties an atomic setup in multi instances environment.\n            (var locker, var locked) = await _distributedLock.TryAcquireAutoSetupLockAsync(_lockOptions);\n            if (!locked)\n            {\n                throw new TimeoutException($\"Fails to acquire an auto setup lock for the tenant: {_setupOptions.ShellName}\");\n            }\n\n            await using var acquiredLock = locker;\n\n            if (_shellSettings.IsUninitialized())\n            {\n                var pathBase = httpContext.Request.PathBase;\n                if (!pathBase.HasValue)\n                {\n                    pathBase = \"/\";\n                }\n\n                // Check if the tenant was installed by another instance.\n                using var settings = await _shellSettingsManager.LoadSettingsAsync(_shellSettings.Name);\n\n                if (settings != null)\n                {\n                    settings.AsDisposable();","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs#L83-L119","documentation":"AutoSetupMiddleware wraps tenant installation in a distributed lock so only one instance performs setup in a multi-instance farm. If TryAcquireAutoSetupLockAsync fails to obtain the lock within the configured timeout, it throws TimeoutException naming the tenant shell. This guarantees atomic setup when several nodes boot simultaneously.","triggerScenarios":"Starting multiple application instances against the same uninitialized tenant at once; a stale lock row held by a crashed or slow instance; lock acquisition/maintenance timeouts set too low in AutoSetupLockOptions.","commonSituations":"Kubernetes/Docker scale-out where replicas race to set up the Default tenant; a previous failed setup left the lock un-released; database latency makes setup exceed the lock timeout.","solutions":["Retry the request/startup once the competing instance finishes setup; the tenant will no longer be uninitialized.","Check for and clear a stale lock (e.g. in the distributed lock store/database) if no other instance is running.","Increase the lock timeout/acquisition options in AutoSetupLockOptions.","Ensure all instances share the same database connection string so the lock is actually distributed."],"exampleFix":"// before\nservices.Configure<AutoSetupLockOptions>(o => o.Timeout = TimeSpan.FromSeconds(5));\n// after\nservices.Configure<AutoSetupLockOptions>(o => o.Timeout = TimeSpan.FromMinutes(2));","handlingStrategy":"retry","validationCode":"// Before booting another instance, confirm no other holder:\n// SELECT * FROM DistributedLock WHERE Name = 'AUTO_SETUP_<tenant>' AND Expires < now -- expect empty","typeGuard":null,"tryCatchPattern":"try { await next.Invoke(context); }\ncatch (TimeoutException ex) when (ex.Message.Contains(\"auto setup lock\"))\n{\n    logger.LogWarning(ex, \"Auto setup lock contention for tenant; another node is setting it up\");\n    await Task.Delay(TimeSpan.FromSeconds(10));\n    // retry or return 503\n}","preventionTips":["Give the lock a generous timeout before scaling out","Avoid launching all replicas simultaneously against an uninitialized tenant","Monitor for stale locks after crashed deployments","Use a shared distributed lock store (database/Redis) across all instances"],"tags":["distributed-lock","setup","multi-instance","timeout"],"backgroundTag":"request-timeout","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}