{"record":{"id":"62d2bcf249bc768e","repo":"gofr-dev/gofr","slug":"w-q","errorCode":null,"errorMessage":"%w: %q","messagePattern":"%w: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/file/ftp/storage_adapter.go","lineNumber":261,"sourceCode":"\tif source == \"\" || dest == \"\" {\n\t\treturn errEmptySourceOrDest\n\t}\n\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","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/file/ftp/storage_adapter.go#L243-L279","documentation":"CopyObject could not find the source object: Retr on the source path returned a not-found-classified error, so the library returns errObjectNotFound wrapping only the source name (no underlying error). The copy was aborted before reading any data.","triggerScenarios":"Calling storageAdapter.CopyObject(ctx, source, dst) where s.conn.Retr(sourcePath) returns an error matched by isFTPNotFoundError.","commonSituations":"Copy scheduled before the producer created the file, source name typo or case mismatch, wrong base path in buildPath, source removed by a cleanup job concurrently.","solutions":["Verify the source exists (StatObject) before copying, or wait/retry until the producer has created it","Check the source name spelling and case","Check the base-path configuration used by buildPath","Handle errors.Is(err, errObjectNotFound) distinctly from transfer failures"],"exampleFix":"// before\nerr := store.CopyObject(ctx, \"incoming/a.csv\", \"done/a.csv\")\n// after\nif _, err := store.StatObject(ctx, \"incoming/a.csv\"); err != nil {\n    return fmt.Errorf(\"source not ready: %w\", err) // retry later\n}\nerr = store.CopyObject(ctx, \"incoming/a.csv\", \"done/a.csv\")","handlingStrategy":"validation","validationCode":"if _, err := store.StatObject(ctx, source); err != nil {\n    return fmt.Errorf(\"source %q not ready: %w\", source, err)\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    // wait for producer or skip; distinguish from transfer errors\n}","preventionTips":["Gate copies on the producer signalling file completion (marker/rename pattern)","Verify source spelling, case, and base path","Handle not-found distinctly from transient copy failures"],"tags":["ftp","file-not-found","copy"],"backgroundTag":"ftp-object-not-found","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}