{"record":{"id":"2ed6107f93aceab6","repo":"JamesNK/Newtonsoft.Json","slug":"annotation","errorCode":null,"errorMessage":"annotation","messagePattern":"annotation","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Linq/JToken.cs","lineNumber":2553,"sourceCode":"        /// <summary>\n        /// Creates a new instance of the <see cref=\"JToken\"/>. All child tokens are recursively cloned.\n        /// </summary>\n        /// <param name=\"settings\">A <see cref=\"JsonCloneSettings\"/> object to configure cloning settings.</param>\n        /// <returns>A new instance of the <see cref=\"JToken\"/>.</returns>\n        public JToken DeepClone(JsonCloneSettings settings)\n        {\n            return CloneToken(settings);\n        }\n\n        /// <summary>\n        /// Adds an object to the annotation list of this <see cref=\"JToken\"/>.\n        /// </summary>\n        /// <param name=\"annotation\">The annotation to add.</param>\n        public void AddAnnotation(object annotation)\n        {\n            if (annotation == null)\n            {\n                throw new ArgumentNullException(nameof(annotation));\n            }\n\n            if (_annotations == null)\n            {\n                _annotations = (annotation is object[]) ? new[] { annotation } : annotation;\n            }\n            else\n            {\n                if (!(_annotations is object[] annotations))\n                {\n                    _annotations = new[] { _annotations, annotation };\n                }\n                else\n                {\n                    int index = 0;\n                    while (index < annotations.Length && annotations[index] != null)\n                    {\n                        index++;","sourceCodeStart":2535,"sourceCodeEnd":2571,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Linq/JToken.cs#L2535-L2571","documentation":"A plain ArgumentNullException(nameof(annotation)) raised by JToken.AddAnnotation when the caller passes a null annotation object. Annotations are arbitrary user objects attached to a JToken (the LINQ-to-JSON equivalent of LINQ-to-XML annotations); a null annotation is meaningless because the internal storage distinguishes a single object from an object[] and cannot represent null, so it is rejected up front.","triggerScenarios":"Calling token.AddAnnotation(null) directly, or passing an expression that evaluates to null (e.g. token.AddAnnotation(maybeNullFactory()) ). Also indirectly when a generic helper forwards an unvalidated external value as an annotation.","commonSituations":"Storing diagnostics/metadata on tokens where the producer may legitimately return null; forgetting to null-check before annotating in a generic serialization pipeline.","solutions":["Guard the annotation with a null check before calling AddAnnotation: if (annotation != null) token.AddAnnotation(annotation);","Substitute a sentinel/null-object annotation instead of null if you need to record absence.","Fix the upstream factory to never return null annotations."],"exampleFix":"// before\ntoken.AddAnnotation(metadata);\n\n// after\nif (metadata != null) token.AddAnnotation(metadata);","handlingStrategy":"validation","validationCode":"if (annotation != null) token.AddAnnotation(annotation);","typeGuard":"static bool IsAnnotatable(object? o) => o != null;","tryCatchPattern":"try { token.AddAnnotation(o); } catch (ArgumentNullException) { /* skip null */ }","preventionTips":["Null-check annotation sources before AddAnnotation.","Use a sentinel/null-object instead of null when absence must be recorded.","Validate upstream factories that produce annotations."],"tags":["annotations","argumentnull","null-check","linq-to-json"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}