{"record":{"id":"a52c295567626ca3","repo":"gofr-dev/gofr","slug":"failed-to-read-source-object-q-w","errorCode":null,"errorMessage":"failed to read source object %q: %w","messagePattern":"failed to read source object %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/file/ftp/storage_adapter.go","lineNumber":264,"sourceCode":"\n\tif source == dest {\n\t\treturn errSameSourceAndDest\n\t}\n\n\tif s.conn == nil {\n\t\treturn errFTPClientNotInitialized\n\t}\n\n\t// Read source file\n\tsourcePath := s.buildPath(source)\n\n\tresp, err := s.conn.Retr(sourcePath)\n\tif err != nil {\n\t\tif isFTPNotFoundError(err) {\n\t\t\treturn fmt.Errorf(\"%w: %q\", errObjectNotFound, source)\n\t\t}\n\n\t\treturn fmt.Errorf(\"failed to read source object %q: %w\", source, err)\n\t}\n\n\t// Read all data from source into memory\n\tdata, err := io.ReadAll(resp)\n\n\tcloseErr := resp.Close()\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read source object data %q: %w\", source, err)\n\t}\n\n\tif closeErr != nil {\n\t\treturn fmt.Errorf(\"failed to close source reader for %q: %w\", source, closeErr)\n\t}\n\n\t// Write to destination\n\tdestPath := s.buildPath(dest)\n\tif err := s.conn.Stor(destPath, bytes.NewReader(data)); err != nil {","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/file/ftp/storage_adapter.go#L246-L282","documentation":"CopyObject could not read the source object for a non-not-found reason: Retr failed with an error isFTPNotFoundError did not classify as missing, so it's wrapped in a 'failed to read source object' error with the source name and cause. This covers connection, permission, and server-side failures during the source read phase.","triggerScenarios":"storageAdapter.CopyObject where s.conn.Retr(sourcePath) fails with connection errors, permission-denied, or other non-550 responses; also if io.ReadAll/resp.Close fails later (those produce their own messages, but this one fires at Retr time).","commonSituations":"Idle FTP connection timed out before the copy, source file permissions insufficient, transient server 4xx (busy), TLS session issues, very large files hitting server limits mid-transfer.","solutions":["Inspect the wrapped cause with errors.Unwrap for the exact FTP response code","Re-dial/reconnect the FTP client and retry the copy if the connection was stale","Check read permissions of the FTP user on the source path","Retry with backoff for transient 4xx server responses"],"exampleFix":"// before\nerr := store.CopyObject(ctx, \"src/a.bin\", \"dst/a.bin\") // stale connection\n// after\nftpConn, _ = reconnectFTP(cfg) // fresh connection\nerr = store.CopyObject(ctx, \"src/a.bin\", \"dst/a.bin\")","handlingStrategy":"retry","validationCode":"if ftpConn == nil || !ftpConnected(ftpConn) {\n    return errors.New(\"ftp connection unavailable before copy\")\n}","typeGuard":"func isFTPNotFound(err error) bool { return errors.Is(err, errObjectNotFound) }","tryCatchPattern":"err := store.CopyObject(ctx, source, dst)\nif err != nil && !errors.Is(err, errObjectNotFound) {\n    // reconnect FTP and retry with backoff; check permissions if persistent\n}","preventionTips":["Re-dial idle FTP connections before long copy operations","Check the FTP user's read permissions on source paths","Retry transient 4xx server responses with backoff"],"tags":["ftp","network","copy"],"backgroundTag":"ftp-retr-failed","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}