nats-io/nats-server · error
invalid utf8 for %s %q
Error message
invalid utf8 for %s %q
What it means
A topic (or other MQTT byte field) must be valid UTF-8; the server validates incoming topic bytes with utf8.Valid before routing or storing them. This error means the field's bytes are not decodable as UTF-8, so the server cannot safely process or log it.
Source
Thrown at server/mqtt.go:4329
if payloadSize < 0 {
return fmt.Errorf("invalid remaining length %d for PUBLISH packet", pl)
}
pp.sz = payloadSize
if pp.sz > 0 {
start = r.pos
r.pos += pp.sz
pp.msg = r.buf[start:r.pos]
} else if pp.sz == 0 {
pp.msg = nil
} else {
return errMQTTInvalidPublishLength
}
return nil
}
func mqttValidateTopic(topic []byte, field string) error {
if !utf8.Valid(topic) {
return fmt.Errorf("invalid utf8 for %s %q", field, topic)
}
if bytes.IndexByte(topic, 0) >= 0 {
return fmt.Errorf("invalid null character in %s %q", field, topic)
}
return nil
}
func mqttValidateString(value string, field string) error {
if !utf8.ValidString(value) {
return fmt.Errorf("invalid utf8 for %s %q", field, value)
}
if strings.IndexByte(value, 0) >= 0 {
return fmt.Errorf("invalid null character in %s %q", field, value)
}
return nil
}
func mqttPubTrace(pp *mqttPublish) string {View on GitHub (pinned to 3a66a489d2)
Solutions
- Validate/convert the topic to UTF-8 in the client before sending (encode from the native string type to UTF-8 bytes)
- Reject or sanitize user-supplied topic components that contain non-text bytes
- Check for slicing bugs that cut a multi-byte rune in half and fix the boundary arithmetic
- Upgrade the client library if its topic encoding is non-conformant
Example fix
// before (Go client)
topic := []byte(userInput)
// after
if !utf8.ValidString(userInput) { return errors.New("topic must be valid UTF-8") }
topic := []byte(userInput) Defensive patterns
Strategy: validation
Validate before calling
func validTopic(b []byte) bool { return utf8.Valid(b) && bytes.IndexByte(b, 0) < 0 && len(b) > 0 } Type guard
func isUTF8Bytes(b []byte) bool { return utf8.Valid(b) } Try / catch
if err := publish(topic, payload); err != nil && strings.Contains(err.Error(), "invalid utf8") { sanitizeTopicAndRetry() } Prevention
- Never build topics from raw binary or user bytes without a UTF-8 check
- Beware slicing multibyte runes; cut only at rune boundaries
- Encode legacy charset data (GBK, Latin-1) to UTF-8 before use
- Add a client-side utf8.Valid assertion in your publish helper
When it happens
Trigger: A client sends SUBSCRIBE, PUBLISH, or UNSUBSCRIBE with topic bytes that are invalid UTF-8 (e.g. raw binary data, Latin-1 encoded strings, or truncated multi-byte sequences).
Common situations: Publishing topics built from binary payloads or user input without encoding checks, clients using non-UTF-8 charsets (legacy systems), or byte-level slicing that splits a multi-byte UTF-8 character.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- character not supported for MQTT topics
- invalid null character in %s %q
- ErrBadEncoding
- ErrBadVersion
- MQTT clients over websocket must connect to the Websocket po
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/45a2b3c50c677893.
Report an issue: GitHub.