grpc-ecosystem/grpc-gateway · error
invalid tag entry: %w
Error message
invalid tag entry: %w
What it means
tagName parses a raw top-level `tags` entry to extract its `name`; if the entry is not valid JSON object data decodable into {name}, the parse failure is wrapped as `invalid tag entry: ...`. This happens before mergeTags can deduplicate, so the offending document's tags array contains an entry that is not a well-formed JSON object.
Source
Thrown at openapiv3-merge/internal/merge/merge.go:472
return raw, nil
}
var v any
dec := json.NewDecoder(bytes.NewReader(raw))
dec.UseNumber()
if err := dec.Decode(&v); err != nil {
return nil, err
}
return json.Marshal(v)
}
// tagName extracts the `name` field from a tag entry. Tag entries without
// a name violate the OpenAPI spec and are rejected.
func tagName(raw json.RawMessage) (string, error) {
var t struct {
Name string `json:"name"`
}
if err := json.Unmarshal(raw, &t); err != nil {
return "", fmt.Errorf("invalid tag entry: %w", err)
}
if t.Name == "" {
return "", errors.New("tag entry missing required \"name\"")
}
return t.Name, nil
}
// isJSONNull reports whether raw is the JSON null literal (possibly
// surrounded by whitespace). Empty input also counts as null.
func isJSONNull(raw json.RawMessage) bool {
if len(raw) == 0 {
return true
}
return bytes.Equal(bytes.TrimSpace(raw), []byte("null"))
}
// orderedObject is an insertion-ordered JSON object. It is used for
// `paths`, `webhooks`, and the bucket of unrecognised top-level keys —View on GitHub (pinned to a58a4436a3)
Solutions
- Locate the malformed tags entry in the failing input file and fix its JSON syntax
- Validate the whole input document with `jq . file.json` before merging
- Regenerate the spec from its source generator
- Run each input through a JSON Schema/OpenAPI validator to catch structural issues early
Example fix
// before: {"tags":[{"name":"pets"},{"name":"store",}]}
// after: {"tags":[{"name":"pets"},{"name":"store"}]} Defensive patterns
Strategy: validation
Validate before calling
for _, f := range files {
b, err := os.ReadFile(f)
if err != nil { return err }
var doc struct {
Tags []json.RawMessage `json:"tags"`
}
if err := json.Unmarshal(b, &doc); err != nil { return err }
for i, t := range doc.Tags {
var tag struct{ Name string `json:"name"` }
if err := json.Unmarshal(t, &tag); err != nil {
return fmt.Errorf("%s: tags[%d]: %w", f, i, err)
}
}
} Type guard
func isDecodableTagEntry(raw json.RawMessage) bool {
var t struct{ Name string `json:"name"` }
return json.Unmarshal(raw, &t) == nil
} Try / catch
if err := merge.Merge(inputs); err != nil {
if strings.Contains(err.Error(), "invalid tag entry") {
return fmt.Errorf("fix the tags array in your input specs: %w", err)
}
return err
} Prevention
- Run jq . over every input spec before merging to catch malformed JSON
- Validate specs with an OpenAPI linter (e.g. spectral) in CI
- Avoid scripts that string-concatenate into tags arrays
When it happens
Trigger: An input document's root `tags` array contains an element that is not a decodable JSON value (e.g. a raw fragment like a truncated object, or a non-object the struct decode rejects), encountered during mergeTags of that document.
Common situations: Hand-edited spec where a tag was typo'd or truncated; a script appending to `tags` with a malformed element; concatenation bugs producing partially valid JSON.
Related errors
AI-assisted analysis of grpc-ecosystem/grpc-gateway@a58a4436a3 (2026-09-02).
Data as JSON: /api/errors/ffeb0b68602c8f65.
Report an issue: GitHub.