fatedier/frp · error

%s must be valid UTF-8

Error message

%s must be valid UTF-8

What it means

The identifier contains invalid UTF-8 byte sequences (utf8.ValidString fails). frp requires identifiers to be well-formed UTF-8 so they can be safely logged, compared, and serialized in JSON control messages. This check runs after the empty and length checks, before the printable-character check.

Source

Thrown at pkg/config/v1/validation/name.go:36

	"fmt"
	"unicode"
	"unicode/utf8"
)

const (
	// MaxRunIDLength is the maximum number of bytes accepted for a control run ID.
	MaxRunIDLength = 64
)

func validateIdentifier(value, kind string, maxLength int) error {
	if value == "" {
		return fmt.Errorf("%s cannot be empty", kind)
	}
	if len(value) > maxLength {
		return fmt.Errorf("%s is too long: length %d exceeds maximum %d", kind, len(value), maxLength)
	}
	if !utf8.ValidString(value) {
		return fmt.Errorf("%s must be valid UTF-8", kind)
	}
	for _, r := range value {
		if !unicode.IsPrint(r) {
			return fmt.Errorf("%s contains non-printable character", kind)
		}
	}
	return nil
}

func ValidateRunID(runID string) error {
	return validateIdentifier(runID, "run id", MaxRunIDLength)
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Encode binary IDs as hex or base64 (e.g. hex.EncodeToString(digest[:])) before use
  2. Ensure source strings come from UTF-8 files/inputs
  3. If a hash is needed, prefer the plain UUID string form

Example fix

// before
sum := sha256.Sum256([]byte(name))
runID := string(sum[:]) // raw bytes, invalid UTF-8

// after
sum := sha256.Sum256([]byte(name))
runID := hex.EncodeToString(sum[:])
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

func isValidRunID(s string) bool {
    return s != "" && len(s) <= validation.MaxRunIDLength && utf8.ValidString(s)
}

Prevention

When it happens

Trigger: Passing a run ID built from raw binary (hash digest bytes, random bytes), a C string with embedded NUL decoded as invalid bytes, or text in a legacy 8-bit encoding (Latin-1) to ValidateRunID.

Common situations: Using sha256.Sum256() output directly instead of hex/base64 encoding it; locale-mismatched config files; buffers reused without truncation appending stale bytes.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/3474d7b11613da77. Report an issue: GitHub.