grpc-ecosystem/grpc-gateway · error

%s: tags: %w

Error message

%s: tags: %w

What it means

This error is produced while parse() unmarshals the top-level `tags` array of an OpenAPI document into []json.RawMessage. It wraps the underlying encoding/json error with the input document's name, so you know which file had a malformed `tags` field. The library throws it because `tags` must be a JSON array; any other shape fails to unmarshal.

Source

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

		case "webhooks":
			obj, err := decodeOrderedObject(raw)
			if err != nil {
				return nil, fmt.Errorf("%s: webhooks: %w", in.Name, err)
			}
			d.Webhooks = obj
		case "components":
			if !isJSONNull(raw) {
				if err := json.Unmarshal(raw, d.Components); err != nil {
					return nil, fmt.Errorf("%s: components: %w", in.Name, err)
				}
			}
		case "security":
			if err := json.Unmarshal(raw, &d.Security); err != nil {
				return nil, fmt.Errorf("%s: security: %w", in.Name, err)
			}
		case "tags":
			if err := json.Unmarshal(raw, &d.Tags); err != nil {
				return nil, fmt.Errorf("%s: tags: %w", in.Name, err)
			}
		case "externalDocs":
			d.ExternalDocs = raw
		default:
			d.extras.set(key, raw)
		}
	}
	if _, err := dec.Token(); err != nil {
		return nil, fmt.Errorf("%s: %w", in.Name, err)
	}
	if d.OpenAPI == "" {
		return nil, fmt.Errorf("%s: missing required field \"openapi\"", in.Name)
	}
	if isJSONNull(d.Info) {
		return nil, fmt.Errorf("%s: missing required field \"info\"", in.Name)
	}
	return d, nil
}

View on GitHub (pinned to a58a4436a3)

Solutions

  1. Open the named input file and verify the top-level "tags" value is a JSON array of objects
  2. Run the file through a JSON linter/parser to pinpoint the syntax or type error
  3. Regenerate the document from its source (e.g. protoc) if it was produced by a generator
  4. Fix any templating or conversion step that rewrites the tags section

Example fix

// before
"tags": { "name": "pets" }
// after
"tags": [ { "name": "pets" } ]
Defensive patterns

Strategy: validation

Validate before calling

func tagsIsArray(data []byte) error {
	var doc map[string]json.RawMessage
	if err := json.Unmarshal(data, &doc); err != nil { return err }
	raw, ok := doc["tags"]
	if !ok { return nil }
	var tags []json.RawMessage
	return json.Unmarshal(raw, &tags)
}

Type guard

func isArray(raw json.RawMessage) bool {
	var arr []json.RawMessage
	return json.Unmarshal(raw, &arr) == nil
}

Try / catch

merged, err := merge.Merge(inputs)
if err != nil {
	var tagErr *merge.TagError
	if errors.As(err, &tagErr) { /* handle malformed tags for tagErr.Name */ }
	return fmt.Errorf("merge failed: %w", err)
}

Prevention

When it happens

Trigger: Calling Merge with an Input whose Data contains a top-level "tags" key whose value is not a JSON array (e.g. "tags": {} or "tags": "foo"), or contains entries that are not JSON values decodable by encoding/json.

Common situations: Hand-edited OpenAPI files, a code generator emitting tags as an object instead of an array, templating/config substitution corrupting the JSON, or YAML-to-JSON conversion producing the wrong shape for tags.

Related errors


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