gofr-dev/gofr · error
failed to delete object
Error message
failed to delete object
What it means
errFailedToDeleteObject is returned by DeleteObject when the DELE (or directory removal) command fails after the object was confirmed to exist. It wraps the server-side error, meaning the server refused or could not complete the deletion.
Source
Thrown at pkg/gofr/datasource/file/ftp/storage_adapter.go:29
"time"
"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 {View on GitHub (pinned to 187eb24962)
Solutions
- Check the FTP user has write/delete permission on the parent directory
- For directories, empty them (delete children first) before removal
- Inspect the wrapped error for the server reply code to confirm the cause
- Retry if the object may have been concurrently removed by another process
Defensive patterns
Strategy: validation
Validate before calling
// check permissions/emptiness before delete
info, err := fs.StatObject(ctx, name)
if err != nil { return err }
_ = info // verify it is a deletable file, and dir is empty if removing a directory Type guard
func isDeleteError(err error) bool { return errors.Is(err, ftp.ErrFailedToDeleteObject) } Try / catch
err := fs.DeleteObject(ctx, name)
if errors.Is(err, ftp.ErrFailedToDeleteObject) {
// inspect wrapped server reply; check perms or non-empty dir
return fmt.Errorf("delete %s: %w", name, err)
} Prevention
- Grant delete permission to the service FTP account on target directories
- Delete directory children before removing the directory itself
- Handle races: re-stat after failure to see if the object already vanished
- Avoid deleting from directories other processes write to concurrently
When it happens
Trigger: Calling DeleteObject on a path that exists but cannot be removed: read-only permissions, the path is a non-empty directory, or the server rejects the DELE/RMD command.
Common situations: FTP account lacks delete permission; attempting to delete a directory that still contains entries; file locked by another upload session; object vanished between stat and delete (race).
Related errors
- invalid FTP configuration: host and port are required
- invalid FTP provider
- FTP config is nil
- FTP client is not initialized
- object name is empty
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/c4c8fe1339fd0426.
Report an issue: GitHub.