AlistGo/alist · warning

cannot move to same parent directory

Error message

cannot move to same parent directory

What it means

executeMoveAPI refuses the operation up front: the source link's current ParentLinkID equals the requested destination ParentLinkID, so the move would be a no-op into the same folder. Note the link is fetched with srcLink, _ := d.getLink(ctx, linkID) — if that fetch errors, srcLink is nil and the check is silently skipped, deferring failure to the server.

Source

Thrown at drivers/proton_drive/util.go:690

func (d *ProtonDrive) executeMoveAPI(ctx context.Context, linkID string, req MoveRequest) error {
	//fmt.Printf("DEBUG Move Request - Name: %s\n", req.Name)
	//fmt.Printf("DEBUG Move Request - Hash: %s\n", req.Hash)
	//fmt.Printf("DEBUG Move Request - OriginalHash: %s\n", req.OriginalHash)
	//fmt.Printf("DEBUG Move Request - ParentLinkID: %s\n", req.ParentLinkID)

	//fmt.Printf("DEBUG Move Request - Name length: %d\n", len(req.Name))
	//fmt.Printf("DEBUG Move Request - NameSignatureEmail: %s\n", req.NameSignatureEmail)
	//fmt.Printf("DEBUG Move Request - ContentHash: %v\n", req.ContentHash)
	//fmt.Printf("DEBUG Move Request - NodePassphrase length: %d\n", len(req.NodePassphrase))
	//fmt.Printf("DEBUG Move Request - NodePassphraseSignature length: %d\n", len(req.NodePassphraseSignature))

	//fmt.Printf("DEBUG Move Request - SrcLinkID: %s\n", linkID)
	//fmt.Printf("DEBUG Move Request - DstParentLinkID: %s\n", req.ParentLinkID)
	//fmt.Printf("DEBUG Move Request - ShareID: %s\n", d.MainShare.ShareID)

	srcLink, _ := d.getLink(ctx, linkID)
	if srcLink != nil && srcLink.ParentLinkID == req.ParentLinkID {
		return fmt.Errorf("cannot move to same parent directory")
	}

	moveURL := fmt.Sprintf(d.apiBase+"/drive/v2/volumes/%s/links/%s/move",
		d.MainShare.VolumeID, linkID)

	reqBody, err := json.Marshal(req)
	if err != nil {
		return fmt.Errorf("failed to marshal move request: %w", err)
	}

	httpReq, err := http.NewRequestWithContext(ctx, "PUT", moveURL, bytes.NewReader(reqBody))
	if err != nil {
		return fmt.Errorf("failed to create HTTP request: %w", err)
	}

	httpReq.Header.Set("Authorization", "Bearer "+d.credentials.AccessToken)
	httpReq.Header.Set("Accept", d.protonJson)
	httpReq.Header.Set("X-Pm-Appversion", d.webDriveAV)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Treat as a no-op success in the caller: compare parent IDs before calling DirectMove and return the existing object
  2. In the driver, return a sentinel (e.g. ErrSameParent) or model.Obj nil-error so callers can distinguish no-op from failure
  3. Handle the getLink error instead of discarding it, so a stale link does not bypass the check

Example fix

// before
srcLink, _ := d.getLink(ctx, linkID)
if srcLink != nil && srcLink.ParentLinkID == req.ParentLinkID {
	return fmt.Errorf("cannot move to same parent directory")
}
// after
srcLink, err := d.getLink(ctx, linkID)
if err != nil { return fmt.Errorf("failed to get link: %w", err) }
if srcLink.ParentLinkID == req.ParentLinkID {
	return ErrSameParent // callers treat as no-op success
}
Defensive patterns

Strategy: validation

Validate before calling

// before calling DirectMove, compare parents yourself:
srcLink, _ := d.getLink(ctx, srcID)
dstID := resolveDstParentID(dstDir)
if srcLink != nil && srcLink.ParentLinkID == dstID {
    return srcObj, nil // no-op move, succeed silently
}

Try / catch

if err := d.DirectMove(ctx, src, dst); err != nil {
    if strings.Contains(err.Error(), "cannot move to same parent directory") {
        return src, nil // treat as no-op success
    }
}

Prevention

When it happens

Trigger: DirectMove called where dstDir is already the object's parent (common when a UI issues move on drop-to-same-folder, or path resolution of '/' maps to the same root); duplicate move retries after a partial success.

Common situations: Frontends that optimistically call move on every drag-drop; retry logic re-running an already-completed move; root-path handling where dstParentLinkID resolves to the current parent.

Related errors


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