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
- 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.
- Sanitize with utf8.RuneErrorInString / strings.ToValidUTF8(s, string(utf8.RuneError)) if lossy replacement is acceptable.
- Find the offending source by checking utf8.ValidString on vendor and each UserComment.Value before calling the library, and log/repair the invalid one.
- 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
- Transcode non-UTF-8 metadata (Latin-1 ID3 tags, GBK text) with golang.org/x/text/encoding before use.
- Run utf8.ValidString on vendor and every UserComment.Value as an input gate.
- Use strings.ToValidUTF8 as a last-resort sanitizer when exact fidelity is not required.
- Avoid passing raw bytes from file reads or network payloads directly as metadata strings.
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
- %w: stream count must be one
- %w: coupled count exceeds stream count
- %w: channel map entry is out of range
- %w: invalid family 2 mapping
- %w: unsupported family 1 channel count
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/e093d752a24749ea.
Report an issue: GitHub.