vxcontrol/pentagi · warning

: source and destination are the same for

Error message

%w: source and destination are the same for %q

What it means

This error is returned by moveMultipleSources when a requested source's resolved destination path (dstPath + source name) equals its current path, i.e. moving a resource onto itself. It wraps errResourceInvalid so callers can match the sentinel with errors.Is. The transaction is rolled back so no partial move is applied.

Solutions

  1. Check that FilePath(dstPath, src.Name) != src.Path for each source before calling MoveResource
  2. Filter out no-op entries from the source list client-side
  3. Match errors.Is(err, errResourceInvalid) and treat as success/no-op if the move is meant to be idempotent

Example fix

// before
res, err := svc.MoveResource(ctx, uid, sources, dstPath, false)
// after
filtered := slices.DeleteFunc(sources, func(s Source) bool {
    return resources.FilePath(dstPath, s.Name) == s.Path
})
res, err := svc.MoveResource(ctx, uid, filtered, dstPath, false)
Defensive patterns

Strategy: validation

Validate before calling

for _, s := range sources {
    if resources.FilePath(dstPath, s.Name) == s.Path {
        return fmt.Errorf("no-op move: %q", s.Path)
    }
}

Try / catch

if err := svc.MoveResource(ctx, uid, sources, dstPath, false); err != nil {
    if errors.Is(err, services.ErrResourceInvalid) {
        // treat as no-op / skip
    }
}

Prevention

When it happens

Trigger: Calling MoveResource with multiple sources where one source's target directory already contains (or resolves to) the same path, e.g. moving file 'a.txt' into directory '/' when it already lives at '/a.txt', or moving a dir into its own parent unchanged.

Common situations: Bulk drag-and-drop in a UI where a user drops a file onto the folder it already resides in; scripted bulk moves that compute destinations without checking current location; retries of an idempotent move after a prior success.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/f5bfe2e30db5b5bf. Report an issue: GitHub.

Appendix: source

Thrown at backend/pkg/server/services/resources.go:729

			return result, fmt.Errorf(
				"%w: sources %q and %q share the same base name %q",
				errResourceConflict, prev, src.Path, src.Name,
			)
		}
		basenameToSrc[src.Name] = src.Path
	}

	// Self-move guard: no source may be a directory that contains dstPath.
	for _, src := range srcs {
		if src.IsDir && resources.PathHasPrefix(dstPath, src.Path) {
			tx.Rollback()
			return result, fmt.Errorf(
				"%w: cannot move directory %q into itself", errResourceInvalid, src.Path,
			)
		}
		if resources.FilePath(dstPath, src.Name) == src.Path {
			tx.Rollback()
			return result, fmt.Errorf(
				"%w: source and destination are the same for %q", errResourceInvalid, src.Path,
			)
		}
	}

	// ── Ensure destination directory ──────────────────────────────────────────
	dest, destExists, err := findResourceByPath(tx, uid, dstPath)
	if err != nil {
		tx.Rollback()
		return result, err
	}
	if destExists && !dest.IsDir {
		tx.Rollback()
		return result, fmt.Errorf(
			"%w: destination %q is a file; cannot move multiple sources into it",
			errResourceConflict, dstPath,
		)
	}

View on GitHub (pinned to ea665308ba)