{"record":{"id":"b2cc7fb49e201c73","repo":"pion/webrtc","slug":"w-too-many-user-comments","errorCode":null,"errorMessage":"%w: too many user comments","messagePattern":"%w: too many user comments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/media/oggwriter/oggwriter.go","lineNumber":768,"sourceCode":"\tif err := validateUserComments(comments); err != nil {\n\t\treturn err\n\t}\n\n\topusTags.UserComments = append(opusTags.UserComments, comments...)\n\n\treturn nil\n}\n\nfunc validateOpusTags(opusTags OpusTags) error {\n\treturn validateOpusTagsWithMaxHeaderLen(opusTags, uint64(math.MaxInt))\n}\n\nfunc validateOpusTagsWithMaxHeaderLen(opusTags OpusTags, maxHeaderLen uint64) error {\n\tif err := validateOpusTagString(\"vendor\", opusTags.Vendor); err != nil {\n\t\treturn err\n\t}\n\tif uint64(len(opusTags.UserComments)) > maxUint32Length {\n\t\treturn fmt.Errorf(\"%w: too many user comments\", errInvalidOpusTags)\n\t}\n\n\tif err := validateUserComments(opusTags.UserComments); err != nil {\n\t\treturn err\n\t}\n\n\treturn validateOpusTagsHeaderLen(opusTags, maxHeaderLen)\n}\n\nfunc validateOpusTagsHeaderLen(opusTags OpusTags, maxHeaderLen uint64) error {\n\theaderLen := uint64(len(commentPageSignature)) + 4 + uint64(len(opusTags.Vendor)) + 4\n\tif headerLen > maxHeaderLen {\n\t\treturn fmt.Errorf(\"%w: header is too long\", errInvalidOpusTags)\n\t}\n\n\tfor _, comment := range opusTags.UserComments {\n\t\tuserCommentLen := uint64(len(comment.Comment)) + 1 + uint64(len(comment.Value))\n\t\tcommentFieldLen := 4 + userCommentLen","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/pion/webrtc/blob/8c25dc09fa9e7c09aac4309ead88093d760432b0/pkg/media/oggwriter/oggwriter.go#L750-L786","documentation":"OpusTags comment count is stored in a uint32 field in the comment header, so the number of user comments cannot exceed maxUint32Length (math.MaxUint32). validateOpusTagsWithMaxHeaderLen returns this wrapped errInvalidOpusTags when len(UserComments) exceeds that bound. In practice it guards against corrupted or hostile tag sets producing an unencodable header.","triggerScenarios":"Calling the OpusTags validation path (e.g. via newTrackConfig or a SetOpusTags-style API) with an OpusTags value whose UserComments slice is longer than 4,294,967,295 entries.","commonSituations":"Programmatically appending comments in a loop without bound (applyUserComments appends, so repeated calls accumulate); loading a pre-existing OpusTags blob from untrusted media and passing it through unchanged.","solutions":["Trim the UserComments slice below 2^32 entries (realistically, to a few dozen).","Stop accumulating comments: replace the slice rather than appending to the default tags.","Deduplicate repeated tags (e.g. repeated TITLE/LANGUAGE entries) before validating.","Check errors.Is(err, errInvalidOpusTags) to identify tag validation failures."],"exampleFix":"// before\nfor i := 0; i < 5000000000; i++ { tags.UserComments = append(tags.UserComments, c) }\n// after\nif uint64(len(tags.UserComments)) + uint64(len(newComments)) <= maxUint32Length { tags.UserComments = append(tags.UserComments, newComments...) }","handlingStrategy":"validation","validationCode":"if uint64(len(tags.UserComments)) > 1<<32-1 { return errors.New(\"too many user comments\") }","typeGuard":null,"tryCatchPattern":"if err := writer.SetOpusTags(tags); err != nil {\n    if errors.Is(err, errInvalidOpusTags) { /* drop excess comments and retry */ }\n    return err\n}","preventionTips":["Cap comment count to a sane number (tens, not billions)","Replace UserComments instead of unbounded appends","Deduplicate repeated tag keys before applying","Validate tags loaded from untrusted media before reuse"],"tags":["go","opus","opus-tags","metadata","validation"],"backgroundTag":"invalid-opus-tags","analyzedSha":"8c25dc09fa9e7c09aac4309ead88093d760432b0","analyzedAt":"2026-09-03T21:56:56.182Z","contentChangedAt":"2026-09-03T21:56:56.182Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}