grpc-ecosystem/grpc-gateway · error

%s.%q: %s redefines an entry with a different value

Error message

%s.%q: %s redefines an entry with a different value

What it means

Raised in mergeOrdered when two inputs define the same key (e.g. the same URL path or webhook name) with canonically different values. The merger refuses to silently overwrite conflicting definitions, so it names the field, the key, and the input that caused the conflict.

Source

Thrown at openapiv3-merge/internal/merge/merge.go:312

			return nil, err
		}
		mergeExtras(out.extras, d.extras)
	}
	return out, nil
}

// mergeOrdered appends entries from src into dst, rejecting key collisions
// whose values differ canonically.
func mergeOrdered(field string, dst, src *orderedObject, srcName string) error {
	for _, k := range src.keys {
		v := src.vals[k]
		if existing, ok := dst.get(k); ok {
			same, err := canonicalEqual(existing, v)
			if err != nil {
				return fmt.Errorf("%s.%s: %w", field, k, err)
			}
			if !same {
				return fmt.Errorf("%s.%q: %s redefines an entry with a different value", field, k, srcName)
			}
			continue
		}
		dst.set(k, v)
	}
	return nil
}

// mergeComponents unions each components/* sub-map. Same-named entries
// across inputs must be canonically identical. The sub-maps are walked in
// spec order so error messages are deterministic.
func mergeComponents(dst, src *components, srcName string) error {
	pairs := []struct {
		name string
		dst  *map[string]json.RawMessage
		src  *map[string]json.RawMessage
	}{
		{"schemas", &dst.Schemas, &src.Schemas},

View on GitHub (pinned to a58a4436a3)

Solutions

  1. Rename one of the conflicting paths/webhooks so each key is unique
  2. Make the duplicate entries canonically identical if they are meant to be the same
  3. Remove the redundant duplicate entry from the later input
  4. Fix the generator configuration that maps two operations to the same route

Example fix

// before (b.json)
"/users/{id}": { "get": { ... different ... } }
// after (b.json)
"/users/{id}/v2": { "get": { ... } }
Defensive patterns

Strategy: validation

Validate before calling

func findDuplicatePaths(inputs []merge.Input) map[string][]string {
	seen := map[string][]string{}
	for _, in := range inputs {
		var doc struct { Paths map[string]json.RawMessage `json:"paths"` }
		if json.Unmarshal(in.Data, &doc) != nil { continue }
		for k := range doc.Paths { seen[k] = append(seen[k], in.Name) }
	}
	dups := map[string][]string{}
	for k, v := range seen { if len(v) > 1 { dups[k] = v } }
	return dups
}

Try / catch

merged, err := merge.Merge(inputs)
if err != nil {
	if strings.Contains(err.Error(), "redefines an entry with a different value") {
		// report conflicting route ownership to the owning teams
	}
	return err
}

Prevention

When it happens

Trigger: Calling Merge where docs A and B both define e.g. paths "/users/{id}" (or the same webhook key) with non-identical operation objects — the values differ even after key-order-insensitive canonicalization.

Common situations: Two proto packages accidentally mapping operations to the same route with different definitions, copy-pasted paths edited in one file but not the other, or a template that instantiates overlapping routes.

Related errors


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