{"record":{"id":"86152e6271b392a0","repo":"cloudreve/cloudreve","slug":"file-with-the-same-name-existed-or-unavailable","errorCode":null,"errorMessage":"file with the same name existed or unavailable","messagePattern":"file with the same name existed or unavailable","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/filemanager/driver/local/local.go","lineNumber":134,"sourceCode":"\t}\n\n\treturn file, nil\n}\n\nfunc (handler *Driver) LocalPath(ctx context.Context, path string) string {\n\treturn util.RelativePath(filepath.FromSlash(path))\n}\n\n// Put 将文件流保存到指定目录\nfunc (handler *Driver) Put(ctx context.Context, file *fs.UploadRequest) error {\n\tdefer file.Close()\n\tdst := util.RelativePath(filepath.FromSlash(file.Props.SavePath))\n\n\t// 如果非 Overwrite，则检查是否有重名冲突\n\tif file.Mode&fs.ModeOverwrite != fs.ModeOverwrite {\n\t\tif util.Exists(dst) {\n\t\t\thandler.l.Warning(\"File with the same name existed or unavailable: %s\", dst)\n\t\t\treturn errors.New(\"file with the same name existed or unavailable\")\n\t\t}\n\t}\n\n\tif err := handler.prepareFileDirectory(dst); err != nil {\n\t\treturn err\n\t}\n\n\topenMode := os.O_CREATE | os.O_RDWR\n\t// if file.Mode&fs.ModeOverwrite == fs.ModeOverwrite && file.Offset == 0 {\n\t// \topenMode |= os.O_TRUNC\n\t// }\n\n\tout, err := os.OpenFile(dst, openMode, Perm)\n\tif err != nil {\n\t\thandler.l.Warning(\"Failed to open or create file: %s\", err)\n\t\treturn err\n\t}\n\tdefer out.Close()","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/cloudreve/cloudreve/blob/20c95ad73f3a8bcb72887fea91ff31ab24fa1011/pkg/filemanager/driver/local/local.go#L116-L152","documentation":"Synthesized (not an API error) by OBS driver Delete when at least one key failed to delete while no batch-level request error occurred — i.e. DeleteObjects returned HTTP success but reported per-object errors in delRes.Errors, or an earlier group failed entirely (obs.go:294-326). The message lists the surviving keys via %v. Delete returns (failed, lastError) so callers already receive exactly which keys to retry. Note the debug log prints v.Key twice — v.Message never reaches the log.","triggerScenarios":"Bucket policy denying delete on specific objects; objects under WORM/retention lock; earlier DeleteObjects request failing (whole group appended to failed); objects owned by a different account via cross-account upload.","commonSituations":"Mixed-ownership buckets; compliance-locked objects; intermittent 5xx on one of several 1000-key batches (maxDeleteBatch=1000).","solutions":["Enable debug logging and read each failed key's Code — the Message slot currently logs the key again, so rely on Code","Re-run Delete only for the keys in the returned failed slice (idempotent operation)","Fix the IAM/bucket policy for the reported Code (e.g. AccessDenied)","For retention-locked objects, schedule deletion after lock expiry"],"exampleFix":"// before (logging bug: v.Key printed where v.Message belongs)\nd.l.Debug(\"Failed to delete file: %s, Code:%s, Message:%s\", v.Key, v.Code, v.Key)\n\n// after\nd.l.Debug(\"Failed to delete file: %s, Code:%s, Message:%s\", v.Key, v.Code, v.Message)","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isObsAccessDenied(err error) bool {\n\tvar se *obs.ServiceError\n\treturn errors.As(err, &se) && se.Code == \"AccessDenied\"\n}","tryCatchPattern":"failed, err := d.Delete(ctx, keys...)\nif len(failed) > 0 {\n\t// deletion is idempotent: re-enqueue only the failed keys with a delay;\n\t// treat lastError as diagnostic, not as a reason to fail the whole batch job\n}","preventionTips":["Make delete jobs idempotent with a retry queue keyed on the returned failed slice","Audit bucket policies for delete denials on subsets of objects","Fix the debug log to print v.Message so per-object causes are visible"],"tags":["obs","delete","partial-failure","storage"],"backgroundTag":null,"analyzedSha":"20c95ad73f3a8bcb72887fea91ff31ab24fa1011","analyzedAt":"2026-08-16T01:42:55.403Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}