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

  1. Validate/convert the topic to UTF-8 in the client before sending (encode from the native string type to UTF-8 bytes)
  2. Reject or sanitize user-supplied topic components that contain non-text bytes
  3. Check for slicing bugs that cut a multi-byte rune in half and fix the boundary arithmetic
  4. 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

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

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/45a2b3c50c677893. Report an issue: GitHub.