{"record":{"id":"dc4cdfd74315c894","repo":"dotnet/BenchmarkDotNet","slug":"the-current-operation-allowed-for-root-nodes-only","errorCode":null,"errorMessage":"The current operation allowed for root nodes only, but the value {this} is attached to another node, {Owner}.","messagePattern":"The current operation allowed for root nodes only, but the value (.+?) is attached to another node, (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/BenchmarkDotNet/Characteristics/CharacteristicObject.cs","lineNumber":68,"sourceCode":"            }\n        }\n        #endregion\n\n        #region Assertions\n\n        private void AssertNotFrozen()\n        {\n            if (Frozen)\n            {\n                throw new InvalidOperationException($\"The current object {this} is frozen. Create a copy to modify.\");\n            }\n        }\n\n        private void AssertIsRoot()\n        {\n            if (Owner != null)\n            {\n                throw new InvalidOperationException(\n                    \"The current operation allowed for root nodes only, \" +\n                    $\"but the value {this} is attached to another node, {Owner}.\");\n            }\n        }\n\n        private void AssertIsNonFrozenRoot()\n        {\n            AssertNotFrozen();\n            AssertIsRoot();\n        }\n\n        private static void AssertIsAssignable(Characteristic characteristic, object? value)\n        {\n            if (ReferenceEquals(value, Characteristic.EmptyValue) || ReferenceEquals(value, null))\n            {\n                if (characteristic.HasChildCharacteristics)\n                    throw new ArgumentNullException(characteristic.Id);\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/dotnet/BenchmarkDotNet/blob/b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3/src/BenchmarkDotNet/Characteristics/CharacteristicObject.cs#L50-L86","documentation":"Some CharacteristicObject operations are legal only on root nodes (objects with no Owner parent). AssertIsRoot enforces this by checking Owner == null. A non-root object is one that has been attached as a child of another CharacteristicObject and is therefore part of a frozen composite hierarchy.","triggerScenarios":"Invoking a root-only operation (structural/identity mutations) on a CharacteristicObject that was previously attached as a child of another object, or operating on a sub-characteristic pulled out of a parent rather than on the top-level Job/config.","commonSituations":"Grabbing a nested characteristic object from a Job and trying to reconfigure it directly, or mixing detached and attached objects when building a config graph.","solutions":["Perform the operation on the root object (the Job/Config you own), not on a child/attached sub-object.","Detach by creating a fresh root instance instead of reusing an attached one.","Check obj.Owner == null before calling root-only APIs, or resolve the root via OwnerOrSelf.","Build the object graph bottom-up and attach children last, so root operations happen before attachment."],"exampleFix":"// before - operating on an attached child object\nchild.SomeRootOnlyOperation(); // throws\n\n// after - operate on the root\nroot.SomeRootOnlyOperation();","handlingStrategy":"validation","validationCode":"if (characteristicObject.Owner != null)\n    throw new InvalidOperationException(\"Operation requires a root object; the given object is attached to a parent.\");\n// now safe to call root-only API","typeGuard":"static bool IsRoot(CharacteristicObject o) => o.Owner == null;","tryCatchPattern":"try { obj.SomeRootOnlyOperation(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"root nodes only\"))\n{\n    // resolve the root via OwnerOrSelf and operate there\n}","preventionTips":["Operate only on the top-level Job/Config you own, never on attached child objects.","Build the object graph bottom-up and attach children last.","Check Owner == null before root-only operations."],"tags":["characteristics","object-graph","root-node","job-config","invalidoperation"],"backgroundTag":null,"analyzedSha":"b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3","analyzedAt":"2026-08-13T19:12:24.196Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}