cloudreve/cloudreve · warning
file with the same name existed or unavailable
Error message
file with the same name existed or unavailable
What it means
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.
Source
Thrown at pkg/filemanager/driver/local/local.go:134
}
return file, nil
}
func (handler *Driver) LocalPath(ctx context.Context, path string) string {
return util.RelativePath(filepath.FromSlash(path))
}
// Put 将文件流保存到指定目录
func (handler *Driver) Put(ctx context.Context, file *fs.UploadRequest) error {
defer file.Close()
dst := util.RelativePath(filepath.FromSlash(file.Props.SavePath))
// 如果非 Overwrite,则检查是否有重名冲突
if file.Mode&fs.ModeOverwrite != fs.ModeOverwrite {
if util.Exists(dst) {
handler.l.Warning("File with the same name existed or unavailable: %s", dst)
return errors.New("file with the same name existed or unavailable")
}
}
if err := handler.prepareFileDirectory(dst); err != nil {
return err
}
openMode := os.O_CREATE | os.O_RDWR
// if file.Mode&fs.ModeOverwrite == fs.ModeOverwrite && file.Offset == 0 {
// openMode |= os.O_TRUNC
// }
out, err := os.OpenFile(dst, openMode, Perm)
if err != nil {
handler.l.Warning("Failed to open or create file: %s", err)
return err
}
defer out.Close()View on GitHub (pinned to 20c95ad73f)
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
Example fix
// before (logging bug: v.Key printed where v.Message belongs)
d.l.Debug("Failed to delete file: %s, Code:%s, Message:%s", v.Key, v.Code, v.Key)
// after
d.l.Debug("Failed to delete file: %s, Code:%s, Message:%s", v.Key, v.Code, v.Message) Defensive patterns
Strategy: retry
Type guard
func isObsAccessDenied(err error) bool {
var se *obs.ServiceError
return errors.As(err, &se) && se.Code == "AccessDenied"
} Try / catch
failed, err := d.Delete(ctx, keys...)
if len(failed) > 0 {
// deletion is idempotent: re-enqueue only the failed keys with a delay;
// treat lastError as diagnostic, not as a reason to fail the whole batch job
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Mixed-ownership buckets; compliance-locked objects; intermittent 5xx on one of several 1000-key batches (maxDeleteBatch=1000).
Related errors
- downloader not configured for this node
- failed to delete files: %v
- config path not set
- SlaveSecret is not set, please specify it in config file
- unknown downloader provider
AI-assisted analysis of cloudreve/cloudreve@20c95ad73f (2026-08-16).
Data as JSON: /api/errors/86152e6271b392a0.
Report an issue: GitHub.