{"record":{"id":"d1ff8aca79c6a0e3","repo":"vxcontrol/pentagi","slug":"w-destination-q-is-a-file-cannot-move-multiple","errorCode":null,"errorMessage":"%w: destination %q is a file; cannot move multiple sources into it","messagePattern":"%w: destination %q is a file; cannot move multiple sources into it","errorType":"http","errorClass":null,"httpStatus":409,"severity":"error","filePath":"backend/pkg/server/services/resources.go","lineNumber":743,"sourceCode":"\t\t\t)\n\t\t}\n\t\tif resources.FilePath(dstPath, src.Name) == src.Path {\n\t\t\ttx.Rollback()\n\t\t\treturn result, fmt.Errorf(\n\t\t\t\t\"%w: source and destination are the same for %q\", errResourceInvalid, src.Path,\n\t\t\t)\n\t\t}\n\t}\n\n\t// ── Ensure destination directory ──────────────────────────────────────────\n\tdest, destExists, err := findResourceByPath(tx, uid, dstPath)\n\tif err != nil {\n\t\ttx.Rollback()\n\t\treturn result, err\n\t}\n\tif destExists && !dest.IsDir {\n\t\ttx.Rollback()\n\t\treturn result, fmt.Errorf(\n\t\t\t\"%w: destination %q is a file; cannot move multiple sources into it\",\n\t\t\terrResourceConflict, dstPath,\n\t\t)\n\t}\n\tif !destExists {\n\t\tcreatedDirs, deletedDirs, orphanHashes, dirErr := ensureResourceDirs(tx, uid, dstPath, force)\n\t\tif dirErr != nil {\n\t\t\ttx.Rollback()\n\t\t\treturn result, dirErr\n\t\t}\n\t\tresult.Added = append(result.Added, convertResources(createdDirs)...)\n\t\tresult.DeletedBefore = append(result.DeletedBefore, convertResources(deletedDirs)...)\n\t\tresult.OrphanHashes = append(result.OrphanHashes, orphanHashes...)\n\t}\n\n\t// ── Move each source into destination/<basename> ──────────────────────────\n\t// The inner move functions (moveFileResource / moveDirResource) call\n\t// ensureResourceDirs for the parent of the target path. Since dstPath is","sourceCodeStart":725,"sourceCodeEnd":761,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/services/resources.go#L725-L761","documentation":"moveMultipleSources refuses to proceed when the destination directory path already exists but is a regular file, since multiple sources cannot be moved 'into' a file. It wraps errResourceConflict so callers can distinguish conflicts from invalid input. The transaction is rolled back before returning.","triggerScenarios":"Calling MoveResource with a dstPath that resolves to an existing file resource instead of a directory, e.g. dstPath='/notes' where '/notes' is a stored file; a typo where the user intended '/notes/' as a directory.","commonSituations":"A file and directory share the same name after a prior rename; client passes a selected file's path instead of its parent folder as the drop target; stale UI cache shows a directory that is now a file.","solutions":["Verify the destination is an existing directory (or does not exist) before calling MoveResource","Use a different destination path or rename the conflicting file first","Match errResourceConflict in the caller and surface 'destination is a file' to the user"],"exampleFix":"// before\nsvc.MoveResource(ctx, uid, sources, dstPath, false)\n// after\ndest, exists := findPath(dstPath)\nif exists && !dest.IsDir {\n    return fmt.Errorf(\"destination %q is a file\", dstPath)\n}\nsvc.MoveResource(ctx, uid, sources, dstPath, false)","handlingStrategy":"validation","validationCode":"dest, exists := findResourceByPath(dstPath)\nif exists && !dest.IsDir {\n    return fmt.Errorf(\"destination %q is a file\", dstPath)\n}","typeGuard":null,"tryCatchPattern":"err := svc.MoveResource(ctx, uid, sources, dstPath, false)\nif errors.Is(err, services.ErrResourceConflict) {\n    // prompt user to pick another destination\n}","preventionTips":["Resolve and inspect the destination before multi-source moves","Pass directory paths, never file paths, as dstPath","Refresh resource listings before drop-target operations"],"tags":["resources","move","conflict","destination"],"backgroundTag":"destination-is-a-file-conflict","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}