{"record":{"id":"0e6ceb8e4324ee29","repo":"stride3d/stride","slug":"value-must-be-null-for-action-memberactiontype-setvalue","errorCode":null,"errorMessage":"Value must be null for action != (MemberActionType.SetValue || MemberPathAction.CollectionAdd)","messagePattern":"Value must be null for action != \\(MemberActionType\\.SetValue \\|\\| MemberPathAction\\.CollectionAdd\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Reflection/MemberPath.cs","lineNumber":226,"sourceCode":"\n    /// <summary>\n    /// Pops the last item from the current path.\n    /// </summary>\n    public void Pop()\n    {\n        if (items.Count > 0)\n        {\n            items.RemoveAt(items.Count - 1);\n        }\n    }\n\n    public bool Apply(object rootObject, MemberPathAction actionType, object? value)\n    {\n        ArgumentNullException.ThrowIfNull(rootObject);\n        if (rootObject.GetType().IsValueType) throw new ArgumentException(\"Value type for root objects are not supported\", nameof(rootObject));\n        if (actionType != MemberPathAction.ValueSet && actionType != MemberPathAction.CollectionAdd && value != null)\n        {\n            throw new ArgumentException(\"Value must be null for action != (MemberActionType.SetValue || MemberPathAction.CollectionAdd)\");\n        }\n\n        if (items == null || items.Count == 0)\n        {\n            throw new InvalidOperationException(\"This instance doesn't contain any path. Use Push() methods to populate paths\");\n        }\n\n        var lastItem = items[^1];\n        switch (actionType)\n        {\n            case MemberPathAction.CollectionAdd:\n                if (lastItem is not CollectionPathItem)\n                {\n                    throw new ArgumentException(\"Invalid path [{0}] for action [{1}]. Expecting last path to be a collection item\".ToFormat(this, actionType));\n                }\n                break;\n            case MemberPathAction.CollectionRemove:\n                if (lastItem is not (CollectionPathItem or ArrayPathItem))","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Reflection/MemberPath.cs#L208-L244","documentation":"MemberPath.Apply() validates that the optional 'value' argument is only supplied for actions that can carry a payload: ValueSet and CollectionAdd. For all other actions (CollectionRemove, DictionaryRemove, etc.) a non-null value is meaningless, so the library rejects it with ArgumentException. This keeps the path-mutation API from silently ignoring values it cannot use.","triggerScenarios":"Calling memberPath.Apply(root, MemberPathAction.CollectionRemove, someObject) or Apply(root, MemberPathAction.DictionaryRemove, someObject) with a non-null value instead of Apply(root, action, null).","commonSituations":"Developers reusing a generic Apply wrapper that always passes a value; copying code from a SetValue call site and changing only the action enum; assuming Remove actions accept the item to remove as the value parameter.","solutions":["Pass null as the value argument for non-set actions: Apply(root, MemberPathAction.CollectionRemove, null).","Remove the item via the path itself — for CollectionRemove the last path item identifies the element; no value is needed.","If you actually need to supply a value, switch the action to MemberPathAction.ValueSet (member assignment) or MemberPathAction.CollectionAdd (element insert)."],"exampleFix":"// before\npath.Apply(root, MemberPathAction.CollectionRemove, itemToRemove);\n// after\npath.Apply(root, MemberPathAction.CollectionRemove, null);","handlingStrategy":"validation","validationCode":"bool valueAllowed = action is MemberPathAction.ValueSet or MemberPathAction.CollectionAdd;\nif (!valueAllowed && value != null)\n    throw new ArgumentException($\"value must be null for action {action}\");\npath.Apply(root, action, value);","typeGuard":"static bool ActionAcceptsValue(MemberPathAction a) => a is MemberPathAction.ValueSet or MemberPathAction.CollectionAdd;","tryCatchPattern":"try { path.Apply(root, action, value); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Value must be null\")) { /* pass null or switch action */ }","preventionTips":["Wrap Apply in a helper that maps action -> whether a value is allowed.","Never pass values for *Remove actions; encode removals purely in the path segments."],"tags":["argument-validation","reflection","csharp"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}