{"record":{"id":"228359292f6251ee","repo":"AlistGo/alist","slug":"same-name-files-cannot-be-delete","errorCode":null,"errorMessage":"same-name files cannot be Delete","messagePattern":"same-name files cannot be Delete","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/alias/driver.go","lineNumber":210,"sourceCode":"\t\treturn errors.New(\"same-name dirs cannot be copied to\")\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = fs.Copy(ctx, *srcPath, *dstPath)\n\treturn err\n}\n\nfunc (d *Alias) Remove(ctx context.Context, obj model.Obj) error {\n\tif !d.Writable {\n\t\treturn errs.PermissionDenied\n\t}\n\treqPath, err := d.getReqPath(ctx, obj, false)\n\tif err == nil {\n\t\treturn fs.Remove(ctx, *reqPath)\n\t}\n\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name files cannot be Delete\")\n\t}\n\treturn err\n}\n\nfunc (d *Alias) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) error {\n\tif !d.Writable {\n\t\treturn errs.PermissionDenied\n\t}\n\treqPath, err := d.getReqPath(ctx, dstDir, true)\n\tif err == nil {\n\t\treturn fs.PutDirectly(ctx, *reqPath, s)\n\t}\n\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name dirs cannot be Put\")\n\t}\n\treturn err\n}\n","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/alias/driver.go#L192-L228","documentation":"Returned by Alias.Remove when getReqPath fails with errs.NotImplement: with ProtectSameName enabled, the object to delete exists in multiple destinations under the same alias key, so the driver refuses to pick one (or delete all) and aborts. This guard prevents accidental partial deletion of mirrored data.","triggerScenarios":"ProtectSameName=true; alias key mapping to 2+ destinations; the file/folder resolves in more than one of them; Remove invoked through the alias.","commonSituations":"Attempting to delete through a merged mirror mount; cleanup scripts operating on alias paths hitting objects that exist on every mirror.","solutions":["Delete explicitly on each underlying storage mount","Uniquely key each destination in Paths and delete via the specific key","Keep ProtectSameName on for mirrors and treat this error as the intended safety stop — do not disable it casually","Delete extra copies until only one destination contains the object, then remove via alias"],"exampleFix":"// before\nfs.Remove(ctx, \"/alias/data/old-file.zip\")\n\n// after — explicit per-mirror deletion\nfs.Remove(ctx, \"/netdisk_a/docs/old-file.zip\")\nfs.Remove(ctx, \"/netdisk_b/docs/old-file.zip\")","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"// Go\nfunc isSameNameErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"same-name\")\n}","tryCatchPattern":"if err := d.Remove(ctx, obj); isSameNameErr(err) {\n    // deletion is intentionally blocked on mirrored objects;\n    // enumerate concrete destinations and delete each explicitly\n} else if err != nil { return err }","preventionTips":["Keep ProtectSameName enabled for mirrored mounts — this error is the safety net working as designed","Delete via concrete mounts so each mirror removal is deliberate","Never disable ProtectSameName just to make delete succeed; that deletes only the first match"],"tags":["alias","protect-same-name","delete","data-safety"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}