{"record":{"id":"ab1a2e7adf376749","repo":"Unity-Technologies/UnityCsReference","slug":"invalid-argument-dropposition","errorCode":null,"errorMessage":"Invalid argument: {dropPosition}","messagePattern":"Invalid argument: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Editor/Mono/GUI/TreeView/TreeViewDragging.cs","lineNumber":126,"sourceCode":"        // When hovering outside any items: target and parent is null, dropPos is invalid\n        // If parentItem and targetItem is the same then insert as first child of parent, dropPos is invalid\n        // If parentItem and targetItem is different then use dropPos to insert dragged items relative to targetItem\n        // parentItem can be null when root is visible and hovering above or below the root\n\n        // if targetItem is null then parent can be null if root is visible\n        // if targetitem is null then parent might be valid if root is hidden\n        public virtual DragAndDropVisualMode DoDrag(TreeViewItem<TIdentifier> parentItem, TreeViewItem<TIdentifier> targetItem, bool perform, DropPosition dropPosition) => DoDragInternal(parentItem, targetItem, perform, dropPosition);\n        public virtual DragAndDropVisualMode DoDragInternal(TreeViewItem<TIdentifier> parentItem, TreeViewItem<TIdentifier> targetItem, bool perform, DropPosition dropPosition) => throw new NotImplementedException();\n\n        protected float GetDropBetweenHalfHeight(TreeViewItem<TIdentifier> item, Rect itemRect)\n        {\n            return m_TreeView.data.CanBeParent(item) ? m_TreeView.gui.halfDropBetweenHeight : itemRect.height * 0.5f;\n        }\n\n        void GetPreviousAndNextItemsIgnoringDraggedItems(int targetRow, DropPosition dropPosition, out TreeViewItem<TIdentifier> previousItem, out TreeViewItem<TIdentifier> nextItem)\n        {\n            if (dropPosition != DropPosition.Above && dropPosition != DropPosition.Below)\n                throw new ArgumentException(\"Invalid argument: \" + dropPosition);\n\n            previousItem = nextItem = null;\n            int curPrevRow = (dropPosition == DropPosition.Above) ? targetRow - 1 : targetRow;\n            int curNextRow = (dropPosition == DropPosition.Above) ? targetRow : targetRow + 1;\n\n            while (curPrevRow >= 0)\n            {\n                var curPreviousItem = m_TreeView.data.GetItem(curPrevRow);\n                if (!m_TreeView.IsDraggingItem(curPreviousItem))\n                {\n                    previousItem = curPreviousItem;\n                    break;\n                }\n                curPrevRow--;\n            }\n\n            while (curNextRow < m_TreeView.data.rowCount)\n            {","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/GUI/TreeView/TreeViewDragging.cs#L108-L144","documentation":"Thrown by GetPreviousAndNextItemsIgnoringDraggedItems when the supplied DropPosition is anything other than Above or Below (i.e. Upon or an out-of-range value). The method computes neighboring rows for sibling insertion, an operation that is meaningless for a 'drop onto' position, so it rejects the input with an ArgumentException. The message concatenates the offending enum value so you can see exactly what was passed.","triggerScenarios":"Calling GetPreviousAndNextItemsIgnoringDraggedItems directly with DropPosition.Upon; passing a DropPosition value that the internal drag pipeline only expects to be Above/Below; a custom TreeViewDragging<T> subclass that overrides drag handling and forwards a non-Above/Below DropPosition into sibling-insertion logic; an uninit/default DropPosition (== Upon, value 0) leaking into the path.","commonSituations":"Implementing a custom editor TreeView drag-drop handler and forgetting that 'Upon' is only valid for drop-onto-parent semantics; upgrading Unity where DropPosition enum gained/changed members; copy-pasting a drop handler that works for Upon drops but reusing it for between-row insertion.","solutions":["Ensure the DropPosition passed into sibling-insertion code is strictly DropPosition.Above or DropPosition.Below before calling.","If your code can legitimately receive DropPosition.Upon, branch early and only call this method in the Above/Below branch.","When overriding DoDrag/DoDragInternal, map Upon to Above or Below (or skip the call) instead of forwarding it.","Validate the enum at the boundary of your own method and reject/map unexpected values before they reach TreeView internals."],"exampleFix":"// before\nGetPreviousAndNextItemsIgnoringDraggedItems(row, dropPosition, out prev, out next);\n\n// after\nif (dropPosition != DropPosition.Above && dropPosition != DropPosition.Below)\n    return; // 'Upon' is handled by drop-onto-parent logic elsewhere\nGetPreviousAndNextItemsIgnoringDraggedItems(row, dropPosition, out prev, out next);","handlingStrategy":"validation","validationCode":"static bool IsValidSiblingDropPosition(TreeViewDragging<int>.DropPosition p)\n    => p == TreeViewDragging<int>.DropPosition.Above || p == TreeViewDragging<int>.DropPosition.Below;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat DropPosition.Upon as a distinct branch from Above/Below in every drag handler.","When overriding DoDrag/DoDragInternal, validate the enum before forwarding to sibling-insertion helpers.","Default-initialize DropPosition to Above/Below rather than relying on the 0 (Upon) default in code that reaches these methods."],"tags":["treeview","drag-and-drop","argument","editor-scripting","validation"],"backgroundTag":null,"analyzedSha":"225b0fbdb57cc17d094e8056b71f8314aba56f73","analyzedAt":"2026-08-13T19:07:19.849Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}