gofr-dev/gofr · error

%w: new filename must match the old file's type

Error message

%w: new filename must match the old file's type

What it means

Rename wraps errIncorrectFileType when the extension of the new name differs from the old one, with the message 'new filename must match the old file's type'. Since S3 renames are copy+delete, the library refuses to silently transform what looks like a different kind of object.

Source

Thrown at pkg/gofr/datasource/file/s3/fs.go:358

		f.logger.Logf("%q & %q are same", oldname, newname)
		return nil
	}

	// check if both exist at same location or not
	if path.Dir(oldname) != path.Dir(newname) {
		f.logger.Errorf("%q & %q are not in same location", oldname, newname)
		return fmt.Errorf("%w: renaming as well as moving file to different location is not allowed", ErrOperationNotPermitted)
	}

	// check if it is a directory
	if path.Ext(oldname) == "" {
		return f.renameDirectory(&st, &msg, oldname, newname)
	}

	// check if they are of the same type or not
	if path.Ext(oldname) != path.Ext(newname) {
		f.logger.Errorf("new file must be same as the old file type")
		return fmt.Errorf("%w: new filename must match the old file's type", errIncorrectFileType)
	}

	_, err := f.conn.CopyObject(context.TODO(), &s3.CopyObjectInput{
		Bucket: aws.String(f.config.BucketName),
		// The source object can be up to 5 GB.
		// If the source object is an object that was uploaded by using a multipart upload, the object copy
		// will be a single part object after the source object is copied to the destination bucket.
		CopySource:         aws.String(f.config.BucketName + "/" + oldname),
		Key:                aws.String(newname),
		ContentType:        aws.String(mime.TypeByExtension(path.Ext(newname))),
		ContentDisposition: aws.String("attachment"),
	})
	if err != nil {
		msg = fmt.Sprintf("Error while copying file: %v", err)
		return err
	}

	err = f.Remove(oldname)

View on GitHub (pinned to 187eb24962)

Solutions

  1. Preserve path.Ext(oldname) when constructing the new name.
  2. If conversion is intended, do it explicitly: read, transform, write to the new key, then delete the old object.
  3. Validate names before calling Rename so the caller sees its own validation error instead of this sentinel.

Example fix

// before
newName := "data-2026.json"
fs.Rename("bucket/data.json.bak", "bucket/"+newName) // type mismatch
// after
newName := "data-2026.json.bak"
fs.Rename("bucket/data.json.bak", "bucket/"+newName)
Defensive patterns

Strategy: validation

Validate before calling

func sameExt(old, new string) bool { return path.Ext(old) == path.Ext(new) }
// guard:
if !sameExt(oldName, newName) { /* adjust newName or use explicit conversion */ }

Prevention

When it happens

Trigger: Rename(oldname, newname) on a file (oldname has an extension) where path.Ext(oldname) != path.Ext(newname), e.g. Rename("bucket/data.csv", "bucket/data.parquet").

Common situations: Accidentally appending/replacing extensions during a rename; building generic rename helpers that accept arbitrary new names; users expecting rename to double as format conversion.

Related errors


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