{"record":{"id":"dd74df487bc4f047","repo":"gofr-dev/gofr","slug":"w-renaming-as-well-as-moving-file-to-different-l","errorCode":null,"errorMessage":"%w: renaming as well as moving file to different location is not allowed","messagePattern":"%w: renaming as well as moving file to different location is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/file/s3/fs.go","lineNumber":347,"sourceCode":"\tst := statusErr\n\n\tdefer f.sendOperationStats(&FileLog{\n\t\tOperation: \"RENAME\",\n\t\tLocation:  getLocation(f.config.BucketName),\n\t\tStatus:    &st,\n\t\tMessage:   &msg,\n\t}, time.Now())\n\n\t// check if they have the same name or not\n\tif oldname == newname {\n\t\tf.logger.Logf(\"%q & %q are same\", oldname, newname)\n\t\treturn nil\n\t}\n\n\t// check if both exist at same location or not\n\tif path.Dir(oldname) != path.Dir(newname) {\n\t\tf.logger.Errorf(\"%q & %q are not in same location\", oldname, newname)\n\t\treturn fmt.Errorf(\"%w: renaming as well as moving file to different location is not allowed\", ErrOperationNotPermitted)\n\t}\n\n\t// check if it is a directory\n\tif path.Ext(oldname) == \"\" {\n\t\treturn f.renameDirectory(&st, &msg, oldname, newname)\n\t}\n\n\t// check if they are of the same type or not\n\tif path.Ext(oldname) != path.Ext(newname) {\n\t\tf.logger.Errorf(\"new file must be same as the old file type\")\n\t\treturn fmt.Errorf(\"%w: new filename must match the old file's type\", errIncorrectFileType)\n\t}\n\n\t_, err := f.conn.CopyObject(context.TODO(), &s3.CopyObjectInput{\n\t\tBucket: aws.String(f.config.BucketName),\n\t\t// The source object can be up to 5 GB.\n\t\t// If the source object is an object that was uploaded by using a multipart upload, the object copy\n\t\t// will be a single part object after the source object is copied to the destination bucket.","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/file/s3/fs.go#L329-L365","documentation":"Rename in the S3 filesystem only supports renaming in place: S3 objects cannot be atomically moved between prefixes, so when oldname and newname have different directory components the call is refused with this wrap of the public sentinel ErrOperationNotPermitted. errors.Is(err, s3.ErrOperationNotPermitted) matches.","triggerScenarios":"Calling Rename(oldname, newname) where path.Dir(oldname) != path.Dir(newname), e.g. Rename(\"bucket/dir1/a.txt\", \"bucket/dir2/a.txt\") — effectively a move across locations.","commonSituations":"Porting POSIX os.Rename-based code to the S3 filesystem expecting move semantics; reorganizing objects into different prefixes; generic file-moving utilities wired to the S3 backend.","solutions":["Rename only within the same directory/prefix: same path.Dir for both names.","Implement a move manually: CopyObject to the new key followed by DeleteObject on the old key.","If using the gofr fs API, first change directory/bucket context appropriately, or restructure code to upload directly to the target prefix."],"exampleFix":"// before\nfs.Rename(\"bucket/logs/old.txt\", \"bucket/archive/old.txt\") // not permitted\n// after\n// copy then delete\nfs.Copy? -> use conn.CopyObject(newKey) + DeleteObject(oldKey), or rename in place:\nfs.Rename(\"bucket/logs/old.txt\", \"bucket/logs/renamed.txt\")","handlingStrategy":"validation","validationCode":"func sameDir(old, new string) bool { return path.Dir(old) == path.Dir(new) }\n// guard before calling:\nif !sameDir(oldName, newName) { /* do copy+delete instead of Rename */ }","typeGuard":null,"tryCatchPattern":"if err := fs.Rename(old, new); err != nil {\n    if errors.Is(err, s3datasource.ErrOperationNotPermitted) {\n        // fallback: CopyObject(new) + DeleteObject(old)\n    }\n    return err\n}","preventionTips":["Only rename within the same prefix/directory.","Implement an explicit Move(ctx, src, dst) helper using CopyObject+DeleteObject.","Don't port os.Rename move semantics blindly to S3 backends.","Keep bucket/prefix layout stable to avoid accidental cross-prefix renames."],"tags":["rename","s3","operation-not-permitted","gofr"],"backgroundTag":"operation-not-permitted","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}