kubernetes/kops · error

failed to marshal json: %w

Error message

failed to marshal json: %w

What it means

OIDCKeys.Open() assembles the JWKS-style KeyResponse (service-account signing public keys) and serializes it with json.MarshalIndent before serving it as an io.Reader. If encoding/json cannot marshal the response, this wrapped error is returned. In practice this is nearly impossible with jose.JSONWebKey values, since those structs marshal fine, so it usually indicates a programmer error or an unusual key payload.

Source

Thrown at pkg/model/issuerdiscovery.go:222

		publicKeyDERHash := hasher.Sum(nil)

		keyID := base64.RawURLEncoding.EncodeToString(publicKeyDERHash)

		keys = append(keys, jose.JSONWebKey{
			Key:       publicKey,
			KeyID:     keyID,
			Algorithm: string(jose.RS256),
			Use:       "sig",
		})
	}
	sort.Slice(keys, func(i, j int) bool {
		return keys[i].KeyID < keys[j].KeyID
	})

	keyResponse := KeyResponse{Keys: keys}
	jsonBytes, err := json.MarshalIndent(keyResponse, "", "")
	if err != nil {
		return nil, fmt.Errorf("failed to marshal json: %w", err)
	}

	return bytes.NewReader(jsonBytes), nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check go.mod for a compatible go-jose version and run go mod tidy / upgrade to a known-good release.
  2. If a KeyResponse field was customized, ensure all added fields are JSON-serializable types.
  3. Read the wrapped %w cause in the error to identify the exact JSON marshal failure and fix the offending field.
  4. Rebuild kOps from upstream sources without local struct modifications.

Example fix

// before
type KeyResponse struct {
    Keys []jose.JSONWebKey `json:"keys"`
    Extra map[string]chan int // non-serializable custom field
}
// after
type KeyResponse struct {
    Keys []jose.JSONWebKey `json:"keys"`
    Extra map[string]string
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure response contains only JSON-serializable values
typeKey := reflect.TypeOf(KeyResponse{}).Kind()
if typeKey != reflect.Struct {
    return fmt.Errorf("unexpected KeyResponse type")
}

Type guard

func isJSONSerializable(v interface{}) bool {
    b, err := json.Marshal(v)
    return err == nil && b != nil
}

Try / catch

jsonBytes, err := json.MarshalIndent(keyResponse, "", "")
if err != nil {
    var uerr *json.UnsupportedTypeError
    if errors.As(err, &uerr) {
        log.Printf("unsupported type in JWKS: %v", uerr.Value)
    }
    return nil, fmt.Errorf("failed to marshal json: %w", err)
}

Prevention

When it happens

Trigger: Calling Open() when the assembled []jose.JSONWebKey slice or KeyResponse contains a value encoding/json rejects — e.g. a key object whose json.Marshaler or custom marshalling panics/returns an error (unsupported type like channel/func inside the key struct, or an invalid value in an embedded field).

Common situations: Custom patches/forks of the jose library changing JSONWebKey field types; very old or mismatched gopkg.in/square/go-jose or github.com/go-jose/go-jose versions; adding non-serializable fields to KeyResponse in a local modification.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/ee649999fd61caac. Report an issue: GitHub.