{"record":{"id":"354114d3c755c44a","repo":"AlistGo/alist","slug":"same-name-dirs-cannot-make-sub-dir","errorCode":null,"errorMessage":"same-name dirs cannot make sub-dir","messagePattern":"same-name dirs cannot make sub-dir","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/alias/driver.go","lineNumber":139,"sourceCode":"\t\t\t\t\tlink.PartSize = d.DownloadPartSize * utils.KB\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn link, nil\n\t\t}\n\t}\n\treturn nil, errs.ObjectNotFound\n}\n\nfunc (d *Alias) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {\n\tif !d.Writable {\n\t\treturn errs.PermissionDenied\n\t}\n\treqPath, err := d.getReqPath(ctx, parentDir, true)\n\tif err == nil {\n\t\treturn fs.MakeDir(ctx, stdpath.Join(*reqPath, dirName))\n\t}\n\tif errs.IsNotImplement(err) {\n\t\treturn errors.New(\"same-name dirs cannot make sub-dir\")\n\t}\n\treturn err\n}\n\nfunc (d *Alias) Move(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 moved\")\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 moved to\")","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/alias/driver.go#L121-L157","documentation":"Returned by Alias.MakeDir when getReqPath fails with errs.NotImplement. Per drivers/alias/util.go:130, that happens when ProtectSameName is enabled and the parent path resolves to existing objects in MORE THAN ONE destination mapped under the same alias name — the driver cannot decide which underlying storage should receive the new sub-directory, so it refuses.","triggerScenarios":"ProtectSameName=true in the Addition, two or more lines in Paths sharing the same alias key (e.g. 'data: /a/dir' and 'data: /b/dir'), and the parent directory existing in both /a/dir and /b/dir; then mkdir is invoked on that aliased parent.","commonSituations":"Users mount several storages under one merged name for redundancy, enable ProtectSameName to avoid writing to the wrong one, then attempt create/move/copy operations that must target exactly one backend.","solutions":["Give each destination a unique alias key in Paths (split 'data' into 'data1', 'data2') so targets are unambiguous","Turn off ProtectSameName (accepts first destination that resolves — only if data loss to a 'wrong' backend is acceptable)","Perform the mkdir directly on the underlying storage mount instead of through the alias","Remove one of the duplicate underlying directories so only one destination resolves"],"exampleFix":"# before — same alias key twice, ambiguous with ProtectSameName\ndata: /netdisk_a/docs\ndata: /netdisk_b/docs\n\n# after — unique keys per destination\ndata_a: /netdisk_a/docs\ndata_b: /netdisk_b/docs","handlingStrategy":"validation","validationCode":"// Reject ambiguous multi-destination keys at setup time when ProtectSameName is on\nkeys := map[string]int{}\nfor _, l := range strings.Split(paths, \"\\n\") {\n    l = strings.TrimSpace(l)\n    if l == \"\" { continue }\n    k, _ := getPair(l)\n    keys[k]++\n}\nfor k, n := range keys {\n    if n > 1 && protectSameName {\n        return fmt.Errorf(\"alias key %q maps %d destinations; write ops on it will fail with ProtectSameName\", k, n)\n    }\n}","typeGuard":"// Go\nfunc isSameNameErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"same-name\")\n}","tryCatchPattern":"if err := d.MakeDir(ctx, parent, name); err != nil {\n    if isSameNameErr(err) {\n        // route the operation to a concrete underlying storage instead\n    }\n    return err\n}","preventionTips":["Never map multiple destinations under one alias key if you intend to write through it","Keep merged (multi-destination) mounts read-only via Writable=false","Reserve ProtectSameName for read paths; do all writes through single-key mounts"],"tags":["alias","protect-same-name","ambiguous-target","mkdir"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}