DevToys-app/DevToys · error · FileNotFoundException
Unable to find the indicated file.
Error message
Unable to find the indicated file.
What it means
Thrown by the SimpleSandboxedFileReader constructor (SandboxedFileReader.FromFileInfo path) when the supplied FileInfo reports Exists == false at construction time. SimpleSandboxedFileReader wraps a read-only, share-read file access (FileMode.Open, FileShare.Read, async/sequential). Because FileInfo caches its Exists value, a stale FileInfo from before the file was deleted will still trip this guard.
Source
Thrown at src/app/dev/DevToys.Api/Core/SimpleSandboxedFileReader.cs:21
/// <summary>
/// Represents a read-only access to a file on the file system.
/// </summary>
/// <remarks>
/// The file can be read and accessed multiple times in parallel.
/// In some cases, the file's resulting stream is non-seekable.
/// Disposing the <see cref="SandboxedFileReader"/> will close the access to the file.
/// </remarks>
[DebuggerDisplay($"FileName = {{{nameof(FileName)}}}")]
internal sealed class SimpleSandboxedFileReader : SandboxedFileReader
{
private readonly FileInfo _fileInfo;
internal SimpleSandboxedFileReader(FileInfo fileInfo)
: base(fileInfo.Name)
{
if (!fileInfo.Exists)
{
throw new FileNotFoundException("Unable to find the indicated file.", fileInfo.FullName);
}
_fileInfo = fileInfo;
}
protected override ValueTask<Stream> OpenReadFileAsync(CancellationToken cancellationToken)
{
if (!_fileInfo.Exists)
{
throw new FileNotFoundException("Unable to find the indicated file.", _fileInfo.FullName);
}
return ValueTask.FromResult(
(Stream)new FileStream(
_fileInfo.FullName,
FileMode.Open,
FileAccess.Read,
FileShare.Read,View on GitHub (pinned to 7e12df8448)
Solutions
- Call fileInfo.Refresh() right before constructing the reader so Exists reflects current disk state.
- Guard with `if (!fileInfo.Exists) return;` (or reprompt) before FromFileInfo.
- For user-picked files, re-validate existence immediately before opening and surface a friendly message if missing.
- Wrap FromFileInfo in try/catch (FileNotFoundException) and recover by reprompting or skipping.
Example fix
// before
var reader = SandboxedFileReader.FromFileInfo(fileInfo);
// after
fileInfo.Refresh();
if (!fileInfo.Exists)
{
// reprompt / log / abort
return;
}
var reader = SandboxedFileReader.FromFileInfo(fileInfo); Defensive patterns
Strategy: validation
Validate before calling
// Refresh defeats FileInfo's cached Exists before constructing the reader.
fileInfo.Refresh();
if (!fileInfo.Exists)
{
// file gone — reprompt / abort
return;
}
SandboxedFileReader reader = SandboxedFileReader.FromFileInfo(fileInfo); Try / catch
try
{
SandboxedFileReader reader = SandboxedFileReader.FromFileInfo(fileInfo);
}
catch (FileNotFoundException ex)
{
// source file vanished before construction — reprompt the user or skip
} Prevention
- Call FileInfo.Refresh() immediately before FromFileInfo; the cached Exists value is a common trap.
- Keep the gap between pick and open as short as possible to shrink the TOCTOU window.
- Re-validate user-picked files right before reading and surface a friendly message if missing.
- Construct the reader in the same synchronous step that confirmed existence.
When it happens
Trigger: Constructing SimpleSandboxedFileReader (via SandboxedFileReader.FromFileInfo) with a FileInfo whose underlying file was deleted, moved, or never written; passing a FileInfo captured long before use without calling Refresh(); a picked file the user removed from disk between selection and open.
Common situations: User picks a file in the file dialog then deletes/renames it externally before the read; a temp file cleaned up by the OS or another process; cross-device path resolution where the FileInfo FullName points somewhere unreachable.
Related errors
- Unable to find the indicated file.
- Unable to find the indicated file.
- Unable to find the indicated file.
- Unable to find the indicated file.
- WebKitGTK could not be found. Please verify that the package
AI-assisted analysis of DevToys-app/DevToys@7e12df8448 (2026-08-13).
Data as JSON: /api/errors/b60fee6fc3ca372a.
Report an issue: GitHub.