gofr-dev/gofr · error

failed to list directory

Error message

failed to list directory

What it means

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.

Source

Thrown at pkg/gofr/datasource/file/ftp/storage_adapter.go:31

	"github.com/jlaffaye/ftp"
	"gofr.dev/pkg/gofr/datasource/file"
)

var (
	// Storage adapter errors.
	errFTPConfigNil            = errors.New("FTP config is nil")
	errFTPClientNotInitialized = errors.New("FTP client is not initialized")
	errEmptyObjectName         = errors.New("object name is empty")
	errInvalidOffset           = errors.New("invalid offset: must be >= 0")
	errEmptySourceOrDest       = errors.New("source and destination names cannot be empty")
	errSameSourceAndDest       = errors.New("source and destination are the same")
	errFailedToCreateReader    = errors.New("failed to create reader")
	errFailedToCreateWriter    = errors.New("failed to create writer")
	errObjectNotFound          = errors.New("object not found")
	errFailedToGetObjectAttrs  = errors.New("failed to get object attrs")
	errFailedToDeleteObject    = errors.New("failed to delete object")
	errFailedToListObjects     = errors.New("failed to list objects")
	errFailedToListDirectory   = errors.New("failed to list directory")
	errWriterAlreadyClosed     = errors.New("writer already closed")
	errFTPConfigInvalid        = errors.New("invalid FTP configuration: host and port are required")
)

// Config represents the FTP configuration.
type Config struct {
	Host        string        // FTP server hostname
	User        string        // FTP username
	Password    string        // FTP password
	Port        int           // FTP port
	RemoteDir   string        // Remote directory path. Base Path for all FTP Operations.
	DialTimeout time.Duration // FTP connection timeout
}

// storageAdapter adapts FTP client to implement file.StorageProvider.
type storageAdapter struct {
	cfg  *Config
	conn *ftp.ServerConn

View on GitHub (pinned to 187eb24962)

Solutions

  1. Verify the path is a directory (StatObject) before calling ListDir
  2. Check read permissions on the directory
  3. Confirm the directory exists on the server — case-sensitive paths matter
  4. Inspect the wrapped server error (e.g. 550) to distinguish not-found vs not-a-directory

Example fix

// before
entries, err := fs.ListDir(ctx, "reports/q4.csv") // a file, not a dir
// after
entries, err := fs.ListDir(ctx, "reports/")
Defensive patterns

Strategy: validation

Validate before calling

// verify the path is a directory before ListDir
info, err := fs.StatObject(ctx, dirPath)
if err != nil || info.IsDir() == false { return fmt.Errorf("%s is not a directory", dirPath) }

Type guard

func isListDirError(err error) bool { return errors.Is(err, ftp.ErrFailedToListDirectory) }

Try / catch

entries, err := fs.ListDir(ctx, dir)
if errors.Is(err, ftp.ErrFailedToListDirectory) {
    // path missing or not a directory — verify with StatObject
    return fmt.Errorf("listdir %s: %w", dir, err)
}

Prevention

When it happens

Trigger: Calling ListDir on a path that does not exist, is a regular file, or whose LIST command fails due to permissions or connection problems.

Common situations: 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.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/133c3723aa0c47a7. Report an issue: GitHub.