JosefNemec/Playnite · error · IOException

Failed to read {path}

Error message

Failed to read {path}

What it means

Thrown by ReadFileAsStringSafe after retryAttempts (default 5) retries of File.ReadAllText all fail with IOException. Each retry waits 500 ms to tolerate transient locks; the final throw preserves the last IOException as the inner exception. It is a 'safe' read wrapper that escalates persistent IO contention to the caller.

Source

Thrown at source/Playnite/Common/FileSystem.cs:192

        public static string ReadFileAsStringSafe(string path, int retryAttempts = 5)
        {
            path = Paths.FixPathLength(path);
            IOException ioException = null;
            for (int i = 0; i < retryAttempts; i++)
            {
                try
                {
                    return File.ReadAllText(path);
                }
                catch (IOException exc)
                {
                    logger.Debug($"Can't read from file, trying again. {path}");
                    ioException = exc;
                    Task.Delay(500).Wait();
                }
            }

            throw new IOException($"Failed to read {path}", ioException);
        }

        public static byte[] ReadFileAsBytesSafe(string path, int retryAttempts = 5)
        {
            path = Paths.FixPathLength(path);
            IOException ioException = null;
            for (int i = 0; i < retryAttempts; i++)
            {
                try
                {
                    return File.ReadAllBytes(path);
                }
                catch (IOException exc)
                {
                    logger.Debug($"Can't read from file, trying again. {path}");
                    ioException = exc;
                    Task.Delay(500).Wait();
                }

View on GitHub (pinned to 5911f4e964)

Solutions

  1. Ensure no other process holds an exclusive lock on the file (close other Playnite instances/tools).
  2. Retry the call after a longer delay, or call with a higher retryAttempts count.
  3. Verify the path exists and the process has read permissions.
  4. Exclude the file/​folder from AV real-time scanning if locking is confirmed.

Example fix

// before
string text = FileSystem.ReadFileAsStringSafe(path);

// after
string text;
try
{
    text = FileSystem.ReadFileAsStringSafe(path, retryAttempts: 10);
}
catch (IOException e)
{
    logger.Error(e, $"Could not read {path} after retries");
    throw;
}
Defensive patterns

Strategy: retry

Try / catch

try { return FileSystem.ReadFileAsStringSafe(path, retryAttempts: 10); }
catch (IOException e) { logger.Error(e, $"Unreadable after retries: {path}"); throw; }

Prevention

When it happens

Trigger: Calling ReadFileAsStringSafe(path) where the file is locked by another process/handle for the entire ~2.5 s retry window, or the path is genuinely unreadable (permissions, missing file, IO error).

Common situations: The target file is held open by another Playnite instance or extension; antivirus has an exclusive scan lock; a sync/​cloud-client (OneDrive) is mid-sync; the file was deleted between calls; permissions deny the read.

Related errors


AI-assisted analysis of JosefNemec/Playnite@5911f4e964 (2026-08-13). Data as JSON: /api/errors/f1077798ae6aa339. Report an issue: GitHub.