{"record":{"id":"8525fbba557ddcb4","repo":"AlistGo/alist","slug":"same-name-dirs-cannot-be-put","errorCode":null,"errorMessage":"same-name dirs cannot be Put","messagePattern":"same-name dirs cannot be Put","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/alias/driver.go","lineNumber":224,"sourceCode":"\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\nfunc (d *Alias) PutURL(ctx context.Context, dstDir model.Obj, name, url string) 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.PutURL(ctx, *reqPath, name, url)\n\t}\n\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name files cannot offline download\")\n\t}\n\treturn err\n}\n","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/alias/driver.go#L206-L242","documentation":"Returned by Alias.Put when getReqPath on the destination directory fails with errs.NotImplement: ProtectSameName is on and the upload target folder exists in multiple destinations mapped under the same alias key, so the driver cannot decide which backend receives the uploaded file.","triggerScenarios":"ProtectSameName=true; destination key mapped to multiple Paths lines; the destination folder resolves in two or more backends; a file upload (PutDirectly) targets the alias path.","commonSituations":"Uploading through a merged mount backed by several storages; web-UI drag-and-drop into an aggregated folder that is mirrored everywhere.","solutions":["Upload through a single-destination alias key or the underlying storage mount","Disable ProtectSameName to write to the first resolved destination (may surprise mirrored setups)","Design merged mounts as read-only (Writable=false) and expose dedicated write mounts"],"exampleFix":"# before\nupload: /disk_a/uploads\nupload: /disk_b/uploads\n\n# after\nupload_a: /disk_a/uploads\n# read-only mirror kept under its own key\nmirror_b: /disk_b/uploads","handlingStrategy":"validation","validationCode":"// Only allow uploads through single-destination keys\nif len(d.pathMap[root]) > 1 && d.ProtectSameName {\n    return errors.New(\"upload target mirrored; use a unique key\")\n}","typeGuard":"// Go\nfunc isSameNameErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"same-name\")\n}","tryCatchPattern":"if err := d.Put(ctx, dst, stream, up); isSameNameErr(err) {\n    // re-issue upload to the concrete backend mount\n} else if err != nil { return err }","preventionTips":["Configure upload endpoints as single-backend aliases","Set Writable=false on merged/read mirrors","In upload UIs, offer only unique-key destinations as targets"],"tags":["alias","protect-same-name","upload","ambiguous-target"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}