{"record":{"id":"b725a0ebadb24792","repo":"gofr-dev/gofr","slug":"source-and-destination-names-cannot-be-empty-b725a0","errorCode":null,"errorMessage":"source and destination names cannot be empty","messagePattern":"source and destination names cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/file/ftp/storage_adapter.go","lineNumber":23,"sourceCode":"\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"path\"\n\t\"strings\"\n\t\"time\"\n\n\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","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/file/ftp/storage_adapter.go#L5-L41","documentation":"errEmptySourceOrDest is returned by CopyObject when either the source or destination object name is the empty string. Both names are required to issue the FTP copy operation; the adapter validates them before any network call.","triggerScenarios":"Calling CopyObject(ctx, src, dst) with src == \"\" or dst == \"\", typically from empty config values, untrimmed inputs, or empty path components.","commonSituations":"Rename flows where only one of old/new name was populated; template/config missing one of the two paths; splitting full paths and losing a segment.","solutions":["Validate both source and destination are non-empty before calling CopyObject.","Populate the missing name from config/request data and fail fast with a clear message if absent.","Trim whitespace to avoid names that are non-empty but blank."],"exampleFix":"// before\nerr := adapter.CopyObject(ctx, src, dst) // dst == \"\"\n// after\nif src == \"\" || dst == \"\" {\n    return fmt.Errorf(\"copy requires non-empty source and destination\")\n}\nerr := adapter.CopyObject(ctx, src, dst)","handlingStrategy":"validation","validationCode":"if src == \"\" || dst == \"\" {\n    return fmt.Errorf(\"copy requires both source and destination\")\n}\nif src == dst {\n    return nil // or error\n}","typeGuard":"func validCopyArgs(src, dst string) bool { return src != \"\" && dst != \"\" && src != dst }","tryCatchPattern":"if !validCopyArgs(src, dst) {\n    return fmt.Errorf(\"invalid copy: src=%q dst=%q\", src, dst)\n}\nerr := adapter.CopyObject(ctx, src, dst)","preventionTips":["Validate both names (non-empty, trimmed) before any copy/rename call.","Ensure rename flows supply both old and new names from validated input.","Add unit tests mirroring TestStorageAdapter_CopyObject_EmptySource/Destination."],"tags":["go","ftp","copy","validation"],"backgroundTag":"empty-object-name","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}