grpc-ecosystem/grpc-gateway · error

invalid hexdigit: %c(%U)

Error message

invalid hexdigit: %c(%U)

What it means

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.

Source

Thrown at internal/httprule/parse.go:293

//
// https://www.ietf.org/rfc/rfc3986.txt, P.49
//
//	pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
//	unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
//	sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
//	              / "*" / "+" / "," / ";" / "="
//	pct-encoded   = "%" HEXDIG HEXDIG
func expectPChars(t string) error {
	const (
		init = iota
		pct1
		pct2
	)
	st := init
	for _, r := range t {
		if st != init {
			if !isHexDigit(r) {
				return fmt.Errorf("invalid hexdigit: %c(%U)", r, r)
			}
			switch st {
			case pct1:
				st = pct2
			case pct2:
				st = init
			}
			continue
		}

		// unreserved
		switch {
		case 'A' <= r && r <= 'Z':
			continue
		case 'a' <= r && r <= 'z':
			continue
		case '0' <= r && r <= '9':
			continue

View on GitHub (pinned to a58a4436a3)

Solutions

  1. Use a valid two-hex-digit escape (%2F, %20, etc.) or drop the '%' if a literal percent was not intended.
  2. Percent-encode '%' itself as %25 in the path template.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at internal/httprule/parse.go:293 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of grpc-ecosystem/grpc-gateway@a58a4436a3 (2026-09-02). Data as JSON: /api/errors/361774265914b455. Report an issue: GitHub.