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

  1. Enable debug logging and read each failed key's Code — the Message slot currently logs the key again, so rely on Code
  2. Re-run Delete only for the keys in the returned failed slice (idempotent operation)
  3. Fix the IAM/bucket policy for the reported Code (e.g. AccessDenied)
  4. 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

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


AI-assisted analysis of cloudreve/cloudreve@20c95ad73f (2026-08-16). Data as JSON: /api/errors/86152e6271b392a0. Report an issue: GitHub.