grpc-ecosystem/grpc-gateway · error · ErrInvalidPattern

invalid pattern

Error message

invalid pattern

What it means

ErrInvalidPattern is a sentinel error returned by NewPattern when the compiled pattern definition passed in is structurally invalid: an unsupported opcodes version, or an odd number of opcode entries. The pattern cannot be constructed safely, so the library fails fast at startup rather than misbehaving at request time.

Source

Thrown at runtime/pattern.go:17

package runtime

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
	"google.golang.org/grpc/grpclog"
)

var (
	// ErrNotMatch indicates that the given HTTP request path does not match to the pattern.
	ErrNotMatch = errors.New("not match to the path pattern")
	// ErrInvalidPattern indicates that the given definition of Pattern is not valid.
	ErrInvalidPattern = errors.New("invalid pattern")
)

type MalformedSequenceError string

func (e MalformedSequenceError) Error() string {
	return "malformed path escape " + strconv.Quote(string(e))
}

type op struct {
	code    utilities.OpCode
	operand int
}

// Pattern is a template pattern of http request paths defined in
// https://github.com/googleapis/googleapis/blob/master/google/api/http.proto
type Pattern struct {
	// ops is a list of operations
	ops []op

View on GitHub (pinned to a58a4436a3)

Solutions

  1. Regenerate the *_pb.gw.go files with a protoc-gen-grpc-gateway version matching your protoc plugins and proto annotations (run protoc again, don't hand-edit ops/pool)
  2. Ensure the version argument is 1 and the ops slice contains an even number of entries when constructing patterns manually
  3. Pin grpc-gateway v2 consistently across go.mod and code generation tooling

Example fix

// before (hand-edited generated code)
p := runtime.MustPattern(runtime.NewPattern(2, []int{0, 0, 1}, []string{"v1"}, ""))
// after
// regenerate *_pb.gw.go; or construct correctly:
p := runtime.MustPattern(runtime.NewPattern(1, []int{utilities.OpLitPush, 0}, []string{"v1"}, ""))
Defensive patterns

Strategy: validation

Validate before calling

if version != 1 {
    return fmt.Errorf("unsupported pattern version %d", version)
}
if len(ops)%2 != 0 {
    return fmt.Errorf("ops slice must have even length, got %d", len(ops))
}

Type guard

func isValidPatternArgs(version int32, ops []int) bool {
    return version == 1 && len(ops)%2 == 0
}

Try / catch

p, err := runtime.NewPattern(1, ops, pool, verb)
if errors.Is(err, runtime.ErrInvalidPattern) {
    grpclog.Fatalf("bad pattern definition (regenerate *_pb.gw.go): %v", err)
}

Prevention

When it happens

Trigger: Calling runtime.NewPattern(version, ops, pool, verb) where version != 1 (pattern.go:56) or len(ops) is odd (pattern.go:62); typically from generated code or custom pattern construction.

Common situations: Hand-editing or post-processing protoc-gen-grpc-gateway generated *_pb.gw.go files and corrupting the ops/pool arrays; mismatched generated code versions where the opcode encoding version differs; custom gateways building patterns manually.

Related errors


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