vxcontrol/pentagi · warning
%w: source and destination are the same for %q
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.
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)
Solutions
- Check that FilePath(dstPath, src.Name) != src.Path for each source before calling MoveResource
- Filter out no-op entries from the source list client-side
- 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
- Filter no-op sources before bulk moves
- Normalize paths before comparing
- Design move APIs to tolerate idempotent retries
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
- %w: cannot move directory into itself
- %w: destination %q is a file; cannot move multiple sources i
- unsupported subtask status: %s
- permission 'resources.view' required to use resource IDs
- failed to fetch resources: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/f5bfe2e30db5b5bf.
Report an issue: GitHub.