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
- Ensure no other process holds an exclusive lock on the file (close other Playnite instances/tools).
- Retry the call after a longer delay, or call with a higher retryAttempts count.
- Verify the path exists and the process has read permissions.
- 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
- Avoid holding exclusive locks on files Playnite must read.
- Call the *Safe overloads with enough retryAttempts for contended files.
- Confirm path existence/permissions before retrying.
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
- Failed to write to {path}
- Failed to delete {path}
- Cannot add file to database, file not found.
- Source directory does not exist or could not be found: {sour
- Root directory is not set or does not exist.
AI-assisted analysis of JosefNemec/Playnite@5911f4e964 (2026-08-13).
Data as JSON: /api/errors/f1077798ae6aa339.
Report an issue: GitHub.