{"record":{"id":"3474d7b11613da77","repo":"fatedier/frp","slug":"s-must-be-valid-utf-8","errorCode":null,"errorMessage":"%s must be valid UTF-8","messagePattern":"(.+?) must be valid UTF-8","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/validation/name.go","lineNumber":36,"sourceCode":"\t\"fmt\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n)\n\nconst (\n\t// MaxRunIDLength is the maximum number of bytes accepted for a control run ID.\n\tMaxRunIDLength = 64\n)\n\nfunc validateIdentifier(value, kind string, maxLength int) error {\n\tif value == \"\" {\n\t\treturn fmt.Errorf(\"%s cannot be empty\", kind)\n\t}\n\tif len(value) > maxLength {\n\t\treturn fmt.Errorf(\"%s is too long: length %d exceeds maximum %d\", kind, len(value), maxLength)\n\t}\n\tif !utf8.ValidString(value) {\n\t\treturn fmt.Errorf(\"%s must be valid UTF-8\", kind)\n\t}\n\tfor _, r := range value {\n\t\tif !unicode.IsPrint(r) {\n\t\t\treturn fmt.Errorf(\"%s contains non-printable character\", kind)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc ValidateRunID(runID string) error {\n\treturn validateIdentifier(runID, \"run id\", MaxRunIDLength)\n}\n","sourceCodeStart":18,"sourceCodeEnd":49,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/validation/name.go#L18-L49","documentation":"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.","triggerScenarios":"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.","commonSituations":"Using sha256.Sum256() output directly instead of hex/base64 encoding it; locale-mismatched config files; buffers reused without truncation appending stale bytes.","solutions":["Encode binary IDs as hex or base64 (e.g. hex.EncodeToString(digest[:])) before use","Ensure source strings come from UTF-8 files/inputs","If a hash is needed, prefer the plain UUID string form"],"exampleFix":"// before\nsum := sha256.Sum256([]byte(name))\nrunID := string(sum[:]) // raw bytes, invalid UTF-8\n\n// after\nsum := sha256.Sum256([]byte(name))\nrunID := hex.EncodeToString(sum[:])","handlingStrategy":"validation","validationCode":"func runIDEncodable(s string) bool { return utf8.ValidString(s) }","typeGuard":"func isValidRunID(s string) bool {\n    return s != \"\" && len(s) <= validation.MaxRunIDLength && utf8.ValidString(s)\n}","tryCatchPattern":null,"preventionTips":["hex/base64-encode any binary digest before using it as an identifier","Keep identifiers ASCII-only to sidestep encoding issues entirely"],"tags":["frp","protocol","identifier","utf-8","encoding","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}