files-community/Files · error · DirectoryNotFoundException

Directory was not found from path.

Error message

Directory was not found from path.

What it means

Thrown by FtpStorageService.GetFolderAsync as DirectoryNotFoundException. After connecting and resolving the path via FtpHelpers.GetFtpPath, it calls GetObjectInfo; if the object is null (no such path) or is not a FtpObjectType.Directory (e.g. the id points at a file), it cannot be returned as an IFolder.

Source

Thrown at src/Files.App.Storage/Ftp/FtpStorageService.cs:21

using FluentFTP;
using System.IO;

namespace Files.App.Storage
{
	/// <inheritdoc cref="IFtpStorageService"/>
	public sealed class FtpStorageService : IFtpStorageService
	{
		/// <inheritdoc/>
		public async Task<IFolder> GetFolderAsync(string id, CancellationToken cancellationToken = default)
		{
			using var ftpClient = FtpHelpers.GetFtpClient(id);
			await ftpClient.EnsureConnectedAsync(cancellationToken);

			var ftpPath = FtpHelpers.GetFtpPath(id);
			var item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);
			if (item is null || item.Type != FtpObjectType.Directory)
				throw new DirectoryNotFoundException("Directory was not found from path.");

			return new FtpStorageFolder(ftpPath, item.Name, null);
		}

		/// <inheritdoc/>
		public async Task<IFile> GetFileAsync(string id, CancellationToken cancellationToken = default)
		{
			using var ftpClient = FtpHelpers.GetFtpClient(id);
			await ftpClient.EnsureConnectedAsync(cancellationToken);

			var ftpPath = FtpHelpers.GetFtpPath(id);
			var item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);
			if (item is null || item.Type != FtpObjectType.File)
				throw new FileNotFoundException("File was not found from path.");

			return new FtpStorageFile(ftpPath, item.Name, null);
		}
	}

View on GitHub (pinned to 68c68a58d4)

Solutions

  1. Validate the id format with FtpHelpers before calling; confirm the host/path are correct.
  2. Call GetFileAsync as a fallback - the id may point to a file rather than a folder.
  3. Catch DirectoryNotFoundException and present a 'location no longer available' message, offering to browse the parent.
  4. Verify the FTP account has list permission on the target directory so GetObjectInfo can resolve it.

Example fix

// before
var folder = await service.GetFolderAsync(id, ct);

// after
try { return await service.GetFolderAsync(id, ct); }
catch (DirectoryNotFoundException) {
    if (await ExistsAsync(service, id, ct))
        return await service.GetFileAsync(id, ct); // it was a file, not a folder
    throw;
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the id is a directory before resolving.
var ftpPath = FtpHelpers.GetFtpPath(id);
var info = await ftpClient.GetObjectInfo(ftpPath, token: ct);
if (info is null || info.Type != FtpObjectType.Directory)
    throw new DirectoryNotFoundException(id);

Type guard

static async Task<bool> IsFtpDirectoryAsync(AsyncFtpClient client, string path, CancellationToken ct)
{ var i = await client.GetObjectInfo(path, token: ct); return i is { Type: FtpObjectType.Directory }; }

Try / catch

try { return await service.GetFolderAsync(id, ct); }
catch (DirectoryNotFoundException) { /* offer to open parent or the file variant */ throw; }

Prevention

When it happens

Trigger: GetFolderAsync(id) where id resolves to a non-existent FTP path, or to a path that exists but is a file rather than a directory. Also if GetObjectInfo returns null because the server denied the listing/STAT.

Common situations: Bookmark/pinned location pointing at a deleted or renamed folder; user typing a path that is actually a file; permission settings that hide the entry from STAT/MLST; stale cached ids after server-side reorganization.

Related errors


AI-assisted analysis of files-community/Files@68c68a58d4 (2026-08-13). Data as JSON: /api/errors/410ed1f59aba1399. Report an issue: GitHub.