{"record":{"id":"9a37a6cad7b38cda","repo":"gofr-dev/gofr","slug":"operation-not-permitted","errorCode":null,"errorMessage":"operation not permitted","messagePattern":"operation not permitted","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/file/s3/fs_dir.go","lineNumber":21,"sourceCode":"import (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"mime\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/aws/aws-sdk-go-v2/aws\"\n\t\"github.com/aws/aws-sdk-go-v2/service/s3\"\n\t\"github.com/aws/aws-sdk-go-v2/service/s3/types\"\n\tfile \"gofr.dev/pkg/gofr/datasource/file\"\n)\n\nvar (\n\tErrOperationNotPermitted = errors.New(\"operation not permitted\")\n)\n\n// getBucketName returns the currentS3Bucket.\nfunc getBucketName(filePath string) string {\n\treturn strings.Split(filePath, string(filepath.Separator))[0]\n}\n\n// getLocation returns the absolute path of the S3 bucket.\nfunc getLocation(bucket string) string {\n\treturn path.Join(string(filepath.Separator), bucket)\n}\n\n// Mkdir creates a directory and any necessary parent directories in the S3 bucket.\n//\n// This method creates a pseudo-directory in the S3 bucket by putting objects with the specified path prefixes.\n// Since S3 uses a flat storage structure, directories are represented by object keys with trailing slashes.\n// The method processes the path segments and ensures that each segment (directory) exists in S3.\nfunc (f *FileSystem) Mkdir(name string, _ os.FileMode) error {","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/file/s3/fs_dir.go#L3-L39","documentation":"ErrOperationNotPermitted is the public sentinel for operations the S3 filesystem cannot perform like a POSIX filesystem. It is returned by Rename when trying to move a file to a different location and by ChDir, since S3 has no working-directory concept. Match with errors.Is(err, s3.ErrOperationNotPermitted).","triggerScenarios":"1) Rename(oldname, newname) where the two paths have different parent directories; 2) any call to ChDir on the S3 filesystem.","commonSituations":"Treating the S3 datasource as a drop-in for os.FileSystem (moving files, changing directories); tools ported from local-disk code paths; attempts to implement directory navigation in a flat key-value store.","solutions":["Replace ChDir usage with fully qualified paths (bucket/key) on every call.","For moves, implement copy+delete (CopyObject then DeleteObject) yourself.","Abstract behind an interface that offers move/cd only for real filesystem backends, so S3 backends never receive those calls."],"exampleFix":"// before\nfs.Chdir(\"bucket/subdir\") // not permitted\n// after\nf, _ := fs.Open(\"bucket/subdir/file.txt\") // use full path instead","handlingStrategy":"try-catch","validationCode":"// avoid calling these on S3-backed fs:\nvar _ = interface{ ChDir() error } // guard with capability check at startup\nfunc supportsChDir(fs any) bool { _, ok := fs.(interface{ ChDir() error }); return ok }","typeGuard":null,"tryCatchPattern":"err := fsObj.ChDir()\nif errors.Is(err, s3datasource.ErrOperationNotPermitted) {\n    // use fully qualified bucket/key paths instead\n}","preventionTips":["Never call ChDir on S3-backed filesystems; always use full bucket/key paths.","Replace move operations with explicit CopyObject+DeleteObject.","Feature-detect capabilities behind an interface so S3 backends never receive unsupported calls.","Check errors.Is(err, s3.ErrOperationNotPermitted) to branch behavior cleanly."],"tags":["s3","operation-not-permitted","chdir","rename","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"}