gofr-dev/gofr · error
%w: %q
Error message
%w: %q
What it means
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.
Source
Thrown at pkg/gofr/datasource/file/ftp/storage_adapter.go:261
if source == "" || dest == "" {
return errEmptySourceOrDest
}
if source == dest {
return errSameSourceAndDest
}
if s.conn == nil {
return errFTPClientNotInitialized
}
// Read source file
sourcePath := s.buildPath(source)
resp, err := s.conn.Retr(sourcePath)
if err != nil {
if isFTPNotFoundError(err) {
return fmt.Errorf("%w: %q", errObjectNotFound, source)
}
return fmt.Errorf("failed to read source object %q: %w", source, err)
}
// Read all data from source into memory
data, err := io.ReadAll(resp)
closeErr := resp.Close()
if err != nil {
return fmt.Errorf("failed to read source object data %q: %w", source, err)
}
if closeErr != nil {
return fmt.Errorf("failed to close source reader for %q: %w", source, closeErr)
}
View on GitHub (pinned to 187eb24962)
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
Example fix
// before
err := store.CopyObject(ctx, "incoming/a.csv", "done/a.csv")
// after
if _, err := store.StatObject(ctx, "incoming/a.csv"); err != nil {
return fmt.Errorf("source not ready: %w", err) // retry later
}
err = store.CopyObject(ctx, "incoming/a.csv", "done/a.csv") Defensive patterns
Strategy: validation
Validate before calling
if _, err := store.StatObject(ctx, source); err != nil {
return fmt.Errorf("source %q not ready: %w", source, err)
} Type guard
func isFTPNotFound(err error) bool { return errors.Is(err, errObjectNotFound) } Try / catch
err := store.CopyObject(ctx, source, dst)
if err != nil && errors.Is(err, errObjectNotFound) {
// wait for producer or skip; distinguish from transfer errors
} Prevention
- 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
When it happens
Trigger: Calling storageAdapter.CopyObject(ctx, source, dst) where s.conn.Retr(sourcePath) returns an error matched by isFTPNotFoundError.
Common situations: 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.
Related errors
- source and destination names cannot be empty
- source and destination are the same
- %w %q: %w
- failed to read source object %q: %w
- invalid FTP configuration: host and port are required
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/62d2bcf249bc768e.
Report an issue: GitHub.