{"record":{"id":"410ed1f59aba1399","repo":"files-community/Files","slug":"directory-was-not-found-from-path","errorCode":null,"errorMessage":"Directory was not found from path.","messagePattern":"Directory was not found from path\\.","errorType":"exception","errorClass":"DirectoryNotFoundException","httpStatus":null,"severity":"error","filePath":"src/Files.App.Storage/Ftp/FtpStorageService.cs","lineNumber":21,"sourceCode":"\nusing FluentFTP;\nusing System.IO;\n\nnamespace Files.App.Storage\n{\n\t/// <inheritdoc cref=\"IFtpStorageService\"/>\n\tpublic sealed class FtpStorageService : IFtpStorageService\n\t{\n\t\t/// <inheritdoc/>\n\t\tpublic async Task<IFolder> GetFolderAsync(string id, CancellationToken cancellationToken = default)\n\t\t{\n\t\t\tusing var ftpClient = FtpHelpers.GetFtpClient(id);\n\t\t\tawait ftpClient.EnsureConnectedAsync(cancellationToken);\n\n\t\t\tvar ftpPath = FtpHelpers.GetFtpPath(id);\n\t\t\tvar item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);\n\t\t\tif (item is null || item.Type != FtpObjectType.Directory)\n\t\t\t\tthrow new DirectoryNotFoundException(\"Directory was not found from path.\");\n\n\t\t\treturn new FtpStorageFolder(ftpPath, item.Name, null);\n\t\t}\n\n\t\t/// <inheritdoc/>\n\t\tpublic async Task<IFile> GetFileAsync(string id, CancellationToken cancellationToken = default)\n\t\t{\n\t\t\tusing var ftpClient = FtpHelpers.GetFtpClient(id);\n\t\t\tawait ftpClient.EnsureConnectedAsync(cancellationToken);\n\n\t\t\tvar ftpPath = FtpHelpers.GetFtpPath(id);\n\t\t\tvar item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);\n\t\t\tif (item is null || item.Type != FtpObjectType.File)\n\t\t\t\tthrow new FileNotFoundException(\"File was not found from path.\");\n\n\t\t\treturn new FtpStorageFile(ftpPath, item.Name, null);\n\t\t}\n\t}","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/files-community/Files/blob/68c68a58d4d6a5f7197e07c8fff85cfd4279c78b/src/Files.App.Storage/Ftp/FtpStorageService.cs#L3-L39","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Validate the id format with FtpHelpers before calling; confirm the host/path are correct.","Call GetFileAsync as a fallback - the id may point to a file rather than a folder.","Catch DirectoryNotFoundException and present a 'location no longer available' message, offering to browse the parent.","Verify the FTP account has list permission on the target directory so GetObjectInfo can resolve it."],"exampleFix":"// before\nvar folder = await service.GetFolderAsync(id, ct);\n\n// after\ntry { return await service.GetFolderAsync(id, ct); }\ncatch (DirectoryNotFoundException) {\n    if (await ExistsAsync(service, id, ct))\n        return await service.GetFileAsync(id, ct); // it was a file, not a folder\n    throw;\n}","handlingStrategy":"validation","validationCode":"// Validate the id is a directory before resolving.\nvar ftpPath = FtpHelpers.GetFtpPath(id);\nvar info = await ftpClient.GetObjectInfo(ftpPath, token: ct);\nif (info is null || info.Type != FtpObjectType.Directory)\n    throw new DirectoryNotFoundException(id);","typeGuard":"static async Task<bool> IsFtpDirectoryAsync(AsyncFtpClient client, string path, CancellationToken ct)\n{ var i = await client.GetObjectInfo(path, token: ct); return i is { Type: FtpObjectType.Directory }; }","tryCatchPattern":"try { return await service.GetFolderAsync(id, ct); }\ncatch (DirectoryNotFoundException) { /* offer to open parent or the file variant */ throw; }","preventionTips":["Confirm list/STAT permission so GetObjectInfo can resolve the path.","Distinguish 'deleted' from 'is a file' by trying GetFileAsync as a fallback.","Refresh stale bookmarks/ids after server-side reorganization."],"tags":["ftp","storage","navigation","notfound"],"backgroundTag":null,"analyzedSha":"68c68a58d4d6a5f7197e07c8fff85cfd4279c78b","analyzedAt":"2026-08-13T10:34:54.614Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}