{"record":{"id":"93af073f918a731f","repo":"fatedier/frp","slug":"s-cannot-be-empty","errorCode":null,"errorMessage":"%s cannot be empty","messagePattern":"(.+?) cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/validation/name.go","lineNumber":30,"sourceCode":"// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validation\n\nimport (\n\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}","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/validation/name.go#L12-L48","documentation":"Generic identifier validator (used e.g. by ValidateRunID for the control run ID, max 64 bytes): the value is the empty string. frp requires these identifiers to be non-empty because they key sessions, routing and bookkeeping on the server.","triggerScenarios":"ValidateRunID(\"\") — the server receives a login/register message whose RunID field is empty (malformed client, protocol misuse, or a custom client built against msg.Login). Other call sites pass their own kind label.","commonSituations":"Custom clients or tests constructing frp control messages without setting RunID; protocol-level bugs where the field is dropped during serialization; fuzzing the control connection.","solutions":["Set a non-empty run ID (client normally generates a UUID/metainfo-based ID automatically)","If writing a custom client, populate msg.Login.RunID before dialing frps","If you see this as an frps operator, it usually indicates a broken/old client — update frpc"],"exampleFix":"// before\nlogin := &msg.Login{\n    User: \"\",\n    RunID: \"\",\n}\n\n// after\nlogin := &msg.Login{\n    User: \"\",\n    RunID: uuid.NewString(),\n}","handlingStrategy":"validation","validationCode":"if err := validation.ValidateRunID(runID); err != nil {\n    // reject/repair before sending msg.Login\n}","typeGuard":"func isValidRunID(s string) bool {\n    return s != \"\"\n}","tryCatchPattern":"if err := validation.ValidateRunID(id); err != nil {\n    if strings.Contains(err.Error(), \"cannot be empty\") {\n        id = uuid.NewString() // regenerate and retry once\n    }\n}","preventionTips":["Always generate a run ID (UUID) in custom clients at connect time","Never pass through empty identifiers from upstream data"],"tags":["frp","protocol","identifier","run-id","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}