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

  1. Verify the source exists (StatObject) before copying, or wait/retry until the producer has created it
  2. Check the source name spelling and case
  3. Check the base-path configuration used by buildPath
  4. 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

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


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/62d2bcf249bc768e. Report an issue: GitHub.