pion/webrtc · error

%w: %s is not valid UTF-8

Error message

%w: %s is not valid UTF-8

What it means

validateOpusTagString rejects any string field (vendor or user comment value) that is not valid UTF-8, returning this error wrapped by errInvalidOpusTags. The OpusTags / Vorbis comment spec mandates UTF-8 encoded strings, so non-UTF-8 input (e.g. Latin-1 or raw binary bytes) cannot be written into the Ogg comment header. The %s is the field name, such as "vendor" or "user comment value".

Source

Thrown at pkg/media/oggwriter/oggwriter.go:822

}

func validateUserComment(comment UserComment) error {
	if !isValidCommentName(comment.Comment) {
		return fmt.Errorf("%w: invalid user comment name", errInvalidOpusTags)
	}
	if err := validateOpusTagString("user comment value", comment.Value); err != nil {
		return err
	}
	if uint64(len(comment.Comment))+1+uint64(len(comment.Value)) > maxUint32Length {
		return fmt.Errorf("%w: user comment is too long", errInvalidOpusTags)
	}

	return nil
}

func validateOpusTagString(field, value string) error {
	if !utf8.ValidString(value) {
		return fmt.Errorf("%w: %s is not valid UTF-8", errInvalidOpusTags, field)
	}
	if uint64(len(value)) > maxUint32Length {
		return fmt.Errorf("%w: %s is too long", errInvalidOpusTags, field)
	}

	return nil
}

func isValidCommentName(comment string) bool {
	if comment == "" {
		return false
	}
	for i := 0; i < len(comment); i++ {
		b := comment[i]
		if b < 0x20 || b > 0x7d || b == '=' {
			return false
		}
	}

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Convert the input to valid UTF-8 before constructing OpusTags, e.g. using golang.org/x/text/encoding (charmap.ISO8859_1 / simplifiedchined GBK) decoders or strings.ToValidUTF8.
  2. Sanitize with utf8.RuneErrorInString / strings.ToValidUTF8(s, string(utf8.RuneError)) if lossy replacement is acceptable.
  3. Find the offending source by checking utf8.ValidString on vendor and each UserComment.Value before calling the library, and log/repair the invalid one.
  4. Match the error with errors.Is(err, errInvalidOpusTags); the message names the field so you know whether it was the vendor string or a comment value.

Example fix

// before
tags.Vendor = string(latin1Bytes)
// after
import "golang.org/x/text/encoding/charmap"
dec := charmap.ISO8859_1.NewDecoder()
out, err := dec.Bytes(latin1Bytes)
if err != nil { return err }
tags.Vendor = string(out) // now valid UTF-8
Defensive patterns

Strategy: validation

Validate before calling

func ensureUTF8(field, s string) (string, error) {
	if !utf8.ValidString(s) {
		return "", fmt.Errorf("%s is not valid UTF-8", field)
	}
	return s, nil
}

Type guard

func isValidUTF8(s string) bool { return utf8.ValidString(s) }

Try / catch

if err := writer.WriteOpusTags(tags); err != nil {
	if errors.Is(err, oggwriter.ErrInvalidOpusTags) && strings.Contains(err.Error(), "not valid UTF-8") {
		// re-encode vendor/comments via strings.ToValidUTF8 or a charset decoder, then retry
	}
	return err
}

Prevention

When it happens

Trigger: Passing an OpusTags.Vendor string or a UserComment.Value containing invalid UTF-8 bytes to code that validates OpusTags (validateOpusTagsWithMaxHeaderLen -> validateOpusTagString). In Go, strings can hold arbitrary bytes, e.g. strings built from []byte read as Latin-1, GBK, or raw binary.

Common situations: Reading metadata from a legacy tag format (ID3v1, Latin-1 encoded ID3v2 frames) and passing it through unconverted; decoding filenames or user input from a non-UTF-8 locale; copying raw bytes from a corrupt file; Go code assuming string literals from external sources are valid UTF-8.

Related errors


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