AlistGo/alist · error

same-name dirs cannot be Put

Error message

same-name dirs cannot be Put

What it means

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.

Source

Thrown at drivers/alias/driver.go:224

	if err == nil {
		return fs.Remove(ctx, *reqPath)
	}
	if errs.IsNotImplement(err) {
		return errors.New("same-name files cannot be Delete")
	}
	return err
}

func (d *Alias) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) error {
	if !d.Writable {
		return errs.PermissionDenied
	}
	reqPath, err := d.getReqPath(ctx, dstDir, true)
	if err == nil {
		return fs.PutDirectly(ctx, *reqPath, s)
	}
	if errs.IsNotImplement(err) {
		return errors.New("same-name dirs cannot be Put")
	}
	return err
}

func (d *Alias) PutURL(ctx context.Context, dstDir model.Obj, name, url string) error {
	if !d.Writable {
		return errs.PermissionDenied
	}
	reqPath, err := d.getReqPath(ctx, dstDir, true)
	if err == nil {
		return fs.PutURL(ctx, *reqPath, name, url)
	}
	if errs.IsNotImplement(err) {
		return errors.New("same-name files cannot offline download")
	}
	return err
}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Upload through a single-destination alias key or the underlying storage mount
  2. Disable ProtectSameName to write to the first resolved destination (may surprise mirrored setups)
  3. Design merged mounts as read-only (Writable=false) and expose dedicated write mounts

Example fix

# before
upload: /disk_a/uploads
upload: /disk_b/uploads

# after
upload_a: /disk_a/uploads
# read-only mirror kept under its own key
mirror_b: /disk_b/uploads
Defensive patterns

Strategy: validation

Validate before calling

// Only allow uploads through single-destination keys
if len(d.pathMap[root]) > 1 && d.ProtectSameName {
    return errors.New("upload target mirrored; use a unique key")
}

Type guard

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

Try / catch

if err := d.Put(ctx, dst, stream, up); isSameNameErr(err) {
    // re-issue upload to the concrete backend mount
} else if err != nil { return err }

Prevention

When it happens

Trigger: 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.

Common situations: Uploading through a merged mount backed by several storages; web-UI drag-and-drop into an aggregated folder that is mirrored everywhere.

Related errors


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