microsoft/aspire · warning · TimeoutException

Failed to acquire file lock

Error message

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

What it means

The synchronous FileLock.Acquire retries creating/opening the lock file while another process holds it. If every attempt fails with IOException or UnauthorizedAccessException until the deadline expires, it throws TimeoutException wrapping the last underlying exception, indicating the lock could not be obtained within the timeout.

Solutions

  1. Increase the timeout argument if contention is expected to be short-lived
  2. Check for and remove stale lock files at lockPath left by crashed processes
  3. Fix filesystem permissions on the lock directory so the process can create files
  4. Investigate the wrapped inner exception (via TimeoutException.InnerException) for the real cause (sharing violation vs access denied)
  5. Ensure the other lock holder releases promptly — look for long-lived FileLock instances not disposed

Example fix

// before
using var lockFile = FileLock.Acquire(lockPath, TimeSpan.FromSeconds(5));
// after
try
{
    using var lockFile = FileLock.Acquire(lockPath, TimeSpan.FromSeconds(30));
}
catch (TimeoutException ex)
{
    logger.LogError(ex.InnerException, "Could not acquire lock {LockPath}", lockPath);
    return;
}
Defensive patterns

Strategy: retry

Validate before calling

// Check writability of the lock directory before attempting the lock
new FileInfo(Path.Combine(lockDir, "probe.tmp")).Directory?.Create();
using (var probe = File.Create(Path.Combine(lockDir, "probe.tmp"))) { }

Try / catch

try { using var l = FileLock.Acquire(lockPath, TimeSpan.FromSeconds(30)); /* work */ }
catch (TimeoutException ex) { logger.LogError(ex.InnerException, "Lock {Path} busy", lockPath); }

Prevention

When it happens

Trigger: Calling FileLock.Acquire(lockPath, timeout) while another process holds the lock for the entire timeout period, or the lock file cannot be created due to filesystem permissions or transient OS locks (antivirus, backup).

Common situations: Two AppHost/dashboard processes contending for a shared cache or settings file; a stale lock left by a crashed process; running under a read-only directory or restricted account; AV software briefly holding new files.

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/93277a4bea9e092c. Report an issue: GitHub.

Appendix: source

Thrown at src/Shared/FileLock.cs:74

    /// <param name="timeout">Maximum time to wait for the lock.</param>
    /// <returns>A <see cref="FileLock"/> that releases the lock when disposed.</returns>
    /// <exception cref="TimeoutException">Thrown if the lock cannot be acquired within the timeout period.</exception>
    public static FileLock Acquire(string lockPath, TimeSpan timeout)
    {
        var deadline = DateTime.UtcNow + timeout;
        CreateLockDirectory(lockPath);

        while (true)
        {
            try
            {
                return new FileLock(CreateLockStream(lockPath));
            }
            catch (Exception exception) when (exception is IOException or UnauthorizedAccessException)
            {
                if (DateTime.UtcNow >= deadline)
                {
                    throw new TimeoutException($"Failed to acquire file lock '{lockPath}' within {timeout.TotalSeconds:F0} seconds.", exception);
                }
            }

            Thread.Sleep(s_defaultRetryDelay);
        }
    }

    /// <summary>
    /// Attempts to acquire an exclusive file lock without waiting.
    /// </summary>
    public static FileLock? TryAcquire(string lockPath)
    {
        try
        {
            return Acquire(lockPath);
        }
        catch (Exception exception) when (exception is IOException or UnauthorizedAccessException)
        {

View on GitHub (pinned to 25830f84bd)