{"record":{"id":"8875c42c7018b0b2","repo":"microsoft/aspire","slug":"failed-to-acquire-file-lock-lockpath-within-effectivetimeout","errorCode":null,"errorMessage":"Failed to acquire file lock '{lockPath}' within {effectiveTimeout.TotalSeconds:F0} seconds.","messagePattern":"Failed to acquire file lock '(.+?)' within (.+?) seconds\\.","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"warning","filePath":"src/Shared/FileLock.cs","lineNumber":136,"sourceCode":"            {\n                return new FileLock(CreateLockStream(lockPath));\n            }\n            catch (IOException)\n            {\n                // Sharing violation — another process holds the lock. On Windows the\n                // FileStream constructor throws immediately; on Unix it may also throw\n                // if the file is exclusively locked. Wait and retry.\n            }\n            catch (UnauthorizedAccessException)\n            {\n                // Can occur transiently when the lock file is being deleted\n                // (DeleteOnClose) by the process that just released the lock,\n                // or if an admin/antivirus has the file temporarily locked.\n            }\n\n            if (DateTime.UtcNow >= deadline)\n            {\n                throw new TimeoutException($\"Failed to acquire file lock '{lockPath}' within {effectiveTimeout.TotalSeconds:F0} seconds.\");\n            }\n\n            await Task.Delay(s_defaultRetryDelay, cancellationToken).ConfigureAwait(false);\n        }\n    }\n\n    /// <summary>\n    /// Releases the OS-level file lock and deletes the lock file (<see cref=\"FileOptions.DeleteOnClose\"/>).\n    /// </summary>\n    public void Dispose()\n    {\n        _stream.Dispose();\n    }\n\n    private static void CreateLockDirectory(string lockPath)\n    {\n        var directory = Path.GetDirectoryName(lockPath);\n        if (!string.IsNullOrEmpty(directory))","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Shared/FileLock.cs#L118-L154","documentation":"The asynchronous FileLock.AcquireAsync loops attempting to acquire the lock file and throws TimeoutException when the deadline elapses without success. Unlike the sync path, this exception does not wrap an inner exception; it fires when the lock file remains contended (or uncreatable) for the whole effective timeout.","triggerScenarios":"Awaiting FileLock.AcquireAsync(lockPath, timeout) while another process holds the lock longer than the timeout, or the lock file cannot be created/opened (permissions, deleted-and-recreated race, OS-level file locks).","commonSituations":"Concurrent background jobs writing shared state in ~/.aspire; a crashed predecessor leaving a persistent lock; low-privilege service accounts; slow disk/network shares making create/delete cycles exceed the deadline.","solutions":["Increase the timeout to accommodate expected contention","Dispose FileLock instances promptly in all code paths (including exceptions) to avoid holding the lock unnecessarily","Check for and clean up stale lock files from terminated processes","Verify the process has write access to the lock directory","Catch TimeoutException at the call site and degrade gracefully or retry with backoff"],"exampleFix":"// before\nawait using var lockFile = await FileLock.AcquireAsync(lockPath, TimeSpan.FromSeconds(10), ct);\n// after\nFileLock? lockFile = null;\ntry\n{\n    lockFile = await FileLock.AcquireAsync(lockPath, TimeSpan.FromSeconds(60), ct);\n}\ncatch (TimeoutException)\n{\n    logger.LogWarning(\"Lock {LockPath} busy; skipping this cycle\", lockPath);\n    return;\n}\nfinally\n{\n    lockFile?.Dispose();\n}","handlingStrategy":"retry","validationCode":"// Probe writability and pre-existing lock before the timed acquire\nvar lockDir = Path.GetDirectoryName(lockPath)!;\nif (!Directory.Exists(lockDir)) Directory.CreateDirectory(lockDir);","typeGuard":null,"tryCatchPattern":"try { await using var l = await FileLock.AcquireAsync(lockPath, TimeSpan.FromSeconds(30), ct); /* work */ }\ncatch (TimeoutException) { logger.LogWarning(\"Lock {Path} unavailable after timeout\", lockPath); }","preventionTips":["Always dispose async locks deterministically","Use cancellation tokens and bounded retries around lock acquisition","Monitor for processes holding locks longer than expected","Avoid network shares for lock files where create/delete latency is high"],"tags":["file-lock","timeout","concurrency","async"],"backgroundTag":"request-timeout","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}