{"record":{"id":"133c3723aa0c47a7","repo":"gofr-dev/gofr","slug":"failed-to-list-directory","errorCode":null,"errorMessage":"failed to list directory","messagePattern":"failed to list directory","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/file/ftp/storage_adapter.go","lineNumber":31,"sourceCode":"\t\"github.com/jlaffaye/ftp\"\n\t\"gofr.dev/pkg/gofr/datasource/file\"\n)\n\nvar (\n\t// Storage adapter errors.\n\terrFTPConfigNil            = errors.New(\"FTP config is nil\")\n\terrFTPClientNotInitialized = errors.New(\"FTP client is not initialized\")\n\terrEmptyObjectName         = errors.New(\"object name is empty\")\n\terrInvalidOffset           = errors.New(\"invalid offset: must be >= 0\")\n\terrEmptySourceOrDest       = errors.New(\"source and destination names cannot be empty\")\n\terrSameSourceAndDest       = errors.New(\"source and destination are the same\")\n\terrFailedToCreateReader    = errors.New(\"failed to create reader\")\n\terrFailedToCreateWriter    = errors.New(\"failed to create writer\")\n\terrObjectNotFound          = errors.New(\"object not found\")\n\terrFailedToGetObjectAttrs  = errors.New(\"failed to get object attrs\")\n\terrFailedToDeleteObject    = errors.New(\"failed to delete object\")\n\terrFailedToListObjects     = errors.New(\"failed to list objects\")\n\terrFailedToListDirectory   = errors.New(\"failed to list directory\")\n\terrWriterAlreadyClosed     = errors.New(\"writer already closed\")\n\terrFTPConfigInvalid        = errors.New(\"invalid FTP configuration: host and port are required\")\n)\n\n// Config represents the FTP configuration.\ntype Config struct {\n\tHost        string        // FTP server hostname\n\tUser        string        // FTP username\n\tPassword    string        // FTP password\n\tPort        int           // FTP port\n\tRemoteDir   string        // Remote directory path. Base Path for all FTP Operations.\n\tDialTimeout time.Duration // FTP connection timeout\n}\n\n// storageAdapter adapts FTP client to implement file.StorageProvider.\ntype storageAdapter struct {\n\tcfg  *Config\n\tconn *ftp.ServerConn","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/file/ftp/storage_adapter.go#L13-L49","documentation":"errFailedToListDirectory is returned by ListDir and the internal handleListError helper when listing a directory's entries fails or the target is not a directory. It is the directory-oriented counterpart of errFailedToListObjects. handleListError maps raw server errors (including 550 'not a directory') to this sentinel.","triggerScenarios":"Calling ListDir on a path that does not exist, is a regular file, or whose LIST command fails due to permissions or connection problems.","commonSituations":"Passing a file path where a directory is expected; directory deleted concurrently; FTP user lacks read permission on the directory; 550 responses from servers that do not distinguish not-found from not-a-directory.","solutions":["Verify the path is a directory (StatObject) before calling ListDir","Check read permissions on the directory","Confirm the directory exists on the server — case-sensitive paths matter","Inspect the wrapped server error (e.g. 550) to distinguish not-found vs not-a-directory"],"exampleFix":"// before\nentries, err := fs.ListDir(ctx, \"reports/q4.csv\") // a file, not a dir\n// after\nentries, err := fs.ListDir(ctx, \"reports/\")","handlingStrategy":"validation","validationCode":"// verify the path is a directory before ListDir\ninfo, err := fs.StatObject(ctx, dirPath)\nif err != nil || info.IsDir() == false { return fmt.Errorf(\"%s is not a directory\", dirPath) }","typeGuard":"func isListDirError(err error) bool { return errors.Is(err, ftp.ErrFailedToListDirectory) }","tryCatchPattern":"entries, err := fs.ListDir(ctx, dir)\nif errors.Is(err, ftp.ErrFailedToListDirectory) {\n    // path missing or not a directory — verify with StatObject\n    return fmt.Errorf(\"listdir %s: %w\", dir, err)\n}","preventionTips":["Only pass directory paths to ListDir; route file reads to NewReader","Check case-sensitivity of directory names against server listings","Verify read permission on the directory for the FTP user","Map 550 server replies via errors.Is to distinguish not-found vs not-a-directory"],"tags":["ftp","listing","directory"],"backgroundTag":"ftp-list-failed","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}