{"record":{"id":"d288d1b5c68a2634","repo":"files-community/Files","slug":"directory-already-exists","errorCode":null,"errorMessage":"Directory already exists.","messagePattern":"Directory already exists\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/Files.App.Storage/Ftp/FtpStorageFolder.cs","lineNumber":164,"sourceCode":"\t\t\t\t// Throw exception since flag CreationCollisionOption.GenerateUniqueName was not satisfied\n\t\t\t\tthrow new IOException(\"Couldn't generate unique name. File skipped.\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// File creation failed\n\t\t\t\tthrow new IOException(\"File creation failed.\");\n\t\t\t}\n\t\t}\n\n\t\t/// <inheritdoc/>\n\t\tpublic async Task<IChildFolder> CreateFolderAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)\n\t\t{\n\t\t\tusing var ftpClient = GetFtpClient();\n\t\t\tawait ftpClient.EnsureConnectedAsync(cancellationToken);\n\n\t\t\tvar newPath = $\"{Id}/{desiredName}\";\n\t\t\tif (overwrite && await ftpClient.DirectoryExists(newPath, cancellationToken))\n\t\t\t\tthrow new IOException(\"Directory already exists.\");\n\n\t\t\tvar isSuccessful = await ftpClient.CreateDirectory(newPath, overwrite, cancellationToken);\n\t\t\tif (!isSuccessful)\n\t\t\t\tthrow new IOException(\"Directory was not successfully created.\");\n\n\t\t\treturn new FtpStorageFolder(newPath, desiredName, this);\n\t\t}\n\t}\n}\n","sourceCodeStart":146,"sourceCodeEnd":174,"githubUrl":"https://github.com/files-community/Files/blob/68c68a58d4d6a5f7197e07c8fff85cfd4279c78b/src/Files.App.Storage/Ftp/FtpStorageFolder.cs#L146-L174","documentation":"Thrown by FtpStorageFolder.CreateFolderAsync when the target directory already exists. As with error 1, the guard is INVERTED: `if (overwrite && await ftpClient.DirectoryExists(...))` throws when overwrite is true and the directory exists - the opposite of overwrite semantics. With the default overwrite=false the existence is not caught here and flows into CreateDirectory.","triggerScenarios":"Calling CreateFolderAsync(name, overwrite: true) on an FtpStorageFolder when a directory named {Id}/{desiredName} already exists on the server.","commonSituations":"Re-running a folder-creation step that previously partially succeeded; duplicate directory names in a batch import; automation passing overwrite=true expecting replace semantics.","solutions":["Fix the inverted condition in FtpStorageFolder.cs:163 to `if (!overwrite && await ftpClient.DirectoryExists(newPath, cancellationToken))`.","Pre-check existence and skip or rename when overwrite is not desired.","Catch the IOException and treat an existing-directory result as non-fatal if idempotent creation is acceptable."],"exampleFix":"// before (FtpStorageFolder.cs:163)\nif (overwrite && await ftpClient.DirectoryExists(newPath, cancellationToken))\n    throw new IOException(\"Directory already exists.\");\n\n// after\nif (!overwrite && await ftpClient.DirectoryExists(newPath, cancellationToken))\n    throw new IOException(\"Directory already exists.\");","handlingStrategy":"validation","validationCode":"// Pre-check directory existence before creating.\nvar target = $\"{ftpFolder.Id}/{desiredName}\";\nif (await ftpClient.DirectoryExists(target, ct))\n{\n    if (!overwrite) throw new IOException($\"Directory {desiredName} already exists.\");\n}","typeGuard":null,"tryCatchPattern":"try { await folder.CreateFolderAsync(name, overwrite, ct); }\ncatch (IOException ex) when (ex.Message == \"Directory already exists.\")\n{ /* skip or rename, depending on desired behavior */ }","preventionTips":["Track and fix the inverted-logic guard at FtpStorageFolder.cs:163.","Pre-check DirectoryExists at the call site.","Treat overwrite=true as 'replace', not 'fail if exists'."],"tags":["ftp","storage","logic-bug","folder-creation"],"backgroundTag":null,"analyzedSha":"68c68a58d4d6a5f7197e07c8fff85cfd4279c78b","analyzedAt":"2026-08-13T10:34:54.614Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}