microsoft/aspire · warning · TimeoutException

Failed to acquire file lock

Error message

Failed to acquire file lock '{lockPath}' within {effectiveTimeout.TotalSeconds:F0} seconds.

What it means

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.

Solutions

  1. Increase the timeout to accommodate expected contention
  2. Dispose FileLock instances promptly in all code paths (including exceptions) to avoid holding the lock unnecessarily
  3. Check for and clean up stale lock files from terminated processes
  4. Verify the process has write access to the lock directory
  5. Catch TimeoutException at the call site and degrade gracefully or retry with backoff

Example fix

// before
await using var lockFile = await FileLock.AcquireAsync(lockPath, TimeSpan.FromSeconds(10), ct);
// after
FileLock? lockFile = null;
try
{
    lockFile = await FileLock.AcquireAsync(lockPath, TimeSpan.FromSeconds(60), ct);
}
catch (TimeoutException)
{
    logger.LogWarning("Lock {LockPath} busy; skipping this cycle", lockPath);
    return;
}
finally
{
    lockFile?.Dispose();
}
Defensive patterns

Strategy: retry

Validate before calling

// Probe writability and pre-existing lock before the timed acquire
var lockDir = Path.GetDirectoryName(lockPath)!;
if (!Directory.Exists(lockDir)) Directory.CreateDirectory(lockDir);

Try / catch

try { await using var l = await FileLock.AcquireAsync(lockPath, TimeSpan.FromSeconds(30), ct); /* work */ }
catch (TimeoutException) { logger.LogWarning("Lock {Path} unavailable after timeout", lockPath); }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/8875c42c7018b0b2. Report an issue: GitHub.

Appendix: source

Thrown at src/Shared/FileLock.cs:136

            {
                return new FileLock(CreateLockStream(lockPath));
            }
            catch (IOException)
            {
                // Sharing violation — another process holds the lock. On Windows the
                // FileStream constructor throws immediately; on Unix it may also throw
                // if the file is exclusively locked. Wait and retry.
            }
            catch (UnauthorizedAccessException)
            {
                // Can occur transiently when the lock file is being deleted
                // (DeleteOnClose) by the process that just released the lock,
                // or if an admin/antivirus has the file temporarily locked.
            }

            if (DateTime.UtcNow >= deadline)
            {
                throw new TimeoutException($"Failed to acquire file lock '{lockPath}' within {effectiveTimeout.TotalSeconds:F0} seconds.");
            }

            await Task.Delay(s_defaultRetryDelay, cancellationToken).ConfigureAwait(false);
        }
    }

    /// <summary>
    /// Releases the OS-level file lock and deletes the lock file (<see cref="FileOptions.DeleteOnClose"/>).
    /// </summary>
    public void Dispose()
    {
        _stream.Dispose();
    }

    private static void CreateLockDirectory(string lockPath)
    {
        var directory = Path.GetDirectoryName(lockPath);
        if (!string.IsNullOrEmpty(directory))

View on GitHub (pinned to 25830f84bd)