pion/webrtc · error

%w: payload too short for comment %d

Error message

%w: payload too short for comment %d

What it means

Returned by parseSingleUserComment when the comment's declared length (a little-endian uint32, negative as int if > MaxInt64-style overflow on 32-bit) exceeds the remaining payload bytes, or is negative. The payload cannot contain the full comment body, indicating a corrupt or truncated OpusTags packet.

Source

Thrown at pkg/media/oggreader/oggreader.go:474

		}
		userComments[i] = comment
		pos = nextPos
	}

	return userComments, nil
}

func parseSingleUserComment(payload []byte, pos, u32Size, index int) (UserComment, int, error) {
	if pos+u32Size > len(payload) {
		return UserComment{}, 0, fmt.Errorf("%w: payload too short for comment len %d", errBadOpusTagsSignature, index)
	}

	commentLen32 := binary.LittleEndian.Uint32(payload[pos : pos+u32Size])
	pos += u32Size

	commentLen := int(commentLen32)
	if commentLen < 0 || pos+commentLen > len(payload) {
		return UserComment{}, 0, fmt.Errorf("%w: payload too short for comment %d", errBadOpusTagsSignature, index)
	}

	comment := string(payload[pos : pos+commentLen])
	pos += commentLen

	parts := strings.SplitN(comment, "=", 2)
	if len(parts) != 2 {
		return UserComment{}, 0, fmt.Errorf("%w: invalid comment %d", errBadOpusTagsSignature, index)
	}

	return UserComment{
		Comment: parts[0],
		Value:   parts[1],
	}, pos, nil
}

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Verify file integrity (checksum) and obtain an uncorrupted copy.
  2. Reject untrusted files: treat errors.Is(err, errBadOpusTagsSignature) as invalid input rather than retrying.
  3. Sanitize the file with a metadata tool (opustags, ffmpeg) to rewrite consistent comment lengths.
  4. If building the payload yourself, ensure each comment's length prefix matches the actual comment bytes written.

Example fix

// before: trusting a corrupt file's length field
comments, err := ParseOpusTags(corruptPayload)
// after: guard against oversized declared lengths before parsing
maxLen := len(payload) - pos
if declaredLen > maxLen { return errors.New("comment length exceeds payload") }
comments, err := ParseOpusTags(payload)
Defensive patterns

Strategy: validation

Validate before calling

func commentLengthsInBounds(payload []byte, vendorEnd, u32Size int) bool {
    pos := vendorEnd + u32Size
    for pos+u32Size <= len(payload) {
        l := int(binary.LittleEndian.Uint32(payload[pos : pos+u32Size]))
        pos += u32Size
        if l < 0 || pos+l > len(payload) { return false }
        pos += l
    }
    return true
}

Try / catch

comments, err := ParseOpusTags(payload)
if err != nil {
    if errors.Is(err, errBadOpusTagsSignature) {
        return nil, fmt.Errorf("comment length exceeds payload; rejecting file: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Parsing an OpusTags payload where the length prefix of comment N, once read, points past the end of the payload (pos+commentLen > len(payload)) or underflows to a negative int.

Common situations: Corrupted metadata from bad disk sectors or interrupted downloads, maliciously crafted files with huge comment lengths (denial-of-service vectors), or encoders writing inconsistent length fields.

Related errors


AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03). Data as JSON: /api/errors/debc986df9005be1. Report an issue: GitHub.