{"record":{"id":"8d2238e2b9247791","repo":"AlistGo/alist","slug":"same-name-files-cannot-be-rename","errorCode":null,"errorMessage":"same-name files cannot be Rename","messagePattern":"same-name files cannot be Rename","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/alias/driver.go","lineNumber":174,"sourceCode":"\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name dirs cannot be moved to\")\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn fs.Move(ctx, *srcPath, *dstPath)\n}\n\nfunc (d *Alias) Rename(ctx context.Context, srcObj model.Obj, newName string) error {\n\tif !d.Writable {\n\t\treturn errs.PermissionDenied\n\t}\n\treqPath, err := d.getReqPath(ctx, srcObj, false)\n\tif err == nil {\n\t\treturn fs.Rename(ctx, *reqPath, newName)\n\t}\n\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name files cannot be Rename\")\n\t}\n\treturn err\n}\n\nfunc (d *Alias) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {\n\tif !d.Writable {\n\t\treturn errs.PermissionDenied\n\t}\n\tsrcPath, err := d.getReqPath(ctx, srcObj, false)\n\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name files cannot be copied\")\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\tdstPath, err := d.getReqPath(ctx, dstDir, true)\n\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name dirs cannot be copied to\")","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/alias/driver.go#L156-L192","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename on the underlying storage mount for each mirror explicitly","Split the alias key so each mirror has its own name","Turn ProtectSameName off if diverging the mirrors is intended/acceptable","Prune duplicate copies so only one destination contains the object"],"exampleFix":"// before\nfs.Rename(ctx, \"/alias/data/report.pdf\", \"report-2026.pdf\")\n\n// after — rename each mirror explicitly\nfs.Rename(ctx, \"/netdisk_a/docs/report.pdf\", \"report-2026.pdf\")\nfs.Rename(ctx, \"/netdisk_b/docs/report.pdf\", \"report-2026.pdf\")","handlingStrategy":"validation","validationCode":"// Check for mirrored copies before exposing rename through the alias\nif len(d.pathMap[root]) > 1 && d.ProtectSameName {\n    // renames must go through concrete mounts\n}","typeGuard":"// Go\nfunc isSameNameErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"same-name\")\n}","tryCatchPattern":"if err := d.Rename(ctx, obj, newName); isSameNameErr(err) {\n    // fan the rename out to each concrete backend yourself\n} else if err != nil { return err }","preventionTips":["Rename on the underlying storage when content is mirrored","Disable rename UI on merged alias mounts in your integration","Track mirror membership so you know when an object is ambiguous"],"tags":["alias","protect-same-name","rename","ambiguous-target"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}