{"record":{"id":"361774265914b455","repo":"grpc-ecosystem/grpc-gateway","slug":"invalid-hexdigit-c-u","errorCode":null,"errorMessage":"invalid hexdigit: %c(%U)","messagePattern":"invalid hexdigit: %c\\(%U\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/httprule/parse.go","lineNumber":293,"sourceCode":"//\n// https://www.ietf.org/rfc/rfc3986.txt, P.49\n//\n//\tpchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n//\tunreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n//\tsub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n//\t              / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n//\tpct-encoded   = \"%\" HEXDIG HEXDIG\nfunc expectPChars(t string) error {\n\tconst (\n\t\tinit = iota\n\t\tpct1\n\t\tpct2\n\t)\n\tst := init\n\tfor _, r := range t {\n\t\tif st != init {\n\t\t\tif !isHexDigit(r) {\n\t\t\t\treturn fmt.Errorf(\"invalid hexdigit: %c(%U)\", r, r)\n\t\t\t}\n\t\t\tswitch st {\n\t\t\tcase pct1:\n\t\t\t\tst = pct2\n\t\t\tcase pct2:\n\t\t\t\tst = init\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// unreserved\n\t\tswitch {\n\t\tcase 'A' <= r && r <= 'Z':\n\t\t\tcontinue\n\t\tcase 'a' <= r && r <= 'z':\n\t\t\tcontinue\n\t\tcase '0' <= r && r <= '9':\n\t\t\tcontinue","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/internal/httprule/parse.go#L275-L311","documentation":"Lexical-validation error from expectPChars: while validating a path-template literal against RFC 3986 pchar rules, a '%' started a percent-encoding but the following character is not a hexadecimal digit. The literal contains a malformed escape like '%ZZ'; the error names the offending character and its Unicode code point.","triggerScenarios":"Thrown at internal/httprule/parse.go:293 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use a valid two-hex-digit escape (%2F, %20, etc.) or drop the '%' if a literal percent was not intended.","Percent-encode '%' itself as %25 in the path template."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}