AlistGo/alist · error

same-name files cannot be Rename

Error message

same-name files cannot be Rename

What it means

Returned by Alias.Rename when getReqPath on the object fails with errs.NotImplement: with ProtectSameName enabled the file exists under more than one destination sharing the alias key, so renaming cannot be mapped to a single underlying object.

Source

Thrown at drivers/alias/driver.go:174

	if errs.IsNotImplement(err) {
		return errors.New("same-name dirs cannot be moved to")
	}
	if err != nil {
		return err
	}
	return fs.Move(ctx, *srcPath, *dstPath)
}

func (d *Alias) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
	if !d.Writable {
		return errs.PermissionDenied
	}
	reqPath, err := d.getReqPath(ctx, srcObj, false)
	if err == nil {
		return fs.Rename(ctx, *reqPath, newName)
	}
	if errs.IsNotImplement(err) {
		return errors.New("same-name files cannot be Rename")
	}
	return err
}

func (d *Alias) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
	if !d.Writable {
		return errs.PermissionDenied
	}
	srcPath, err := d.getReqPath(ctx, srcObj, false)
	if errs.IsNotImplement(err) {
		return errors.New("same-name files cannot be copied")
	}
	if err != nil {
		return err
	}
	dstPath, err := d.getReqPath(ctx, dstDir, true)
	if errs.IsNotImplement(err) {
		return errors.New("same-name dirs cannot be copied to")

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Rename on the underlying storage mount for each mirror explicitly
  2. Split the alias key so each mirror has its own name
  3. Turn ProtectSameName off if diverging the mirrors is intended/acceptable
  4. Prune duplicate copies so only one destination contains the object

Example fix

// before
fs.Rename(ctx, "/alias/data/report.pdf", "report-2026.pdf")

// after — rename each mirror explicitly
fs.Rename(ctx, "/netdisk_a/docs/report.pdf", "report-2026.pdf")
fs.Rename(ctx, "/netdisk_b/docs/report.pdf", "report-2026.pdf")
Defensive patterns

Strategy: validation

Validate before calling

// Check for mirrored copies before exposing rename through the alias
if len(d.pathMap[root]) > 1 && d.ProtectSameName {
    // renames must go through concrete mounts
}

Type guard

// Go
func isSameNameErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "same-name")
}

Try / catch

if err := d.Rename(ctx, obj, newName); isSameNameErr(err) {
    // fan the rename out to each concrete backend yourself
} else if err != nil { return err }

Prevention

When it happens

Trigger: ProtectSameName=true; multiple Paths entries with the same key; the object being renamed resolves successfully (fs.Get) in two or more destinations; Rename invoked through the alias.

Common situations: Mirrored mounts where both copies of a file exist; user renames via the alias UI path and the driver refuses rather than renaming only one mirror and silently diverging the mirror set.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/8d2238e2b9247791. Report an issue: GitHub.