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
- Check go.mod for a compatible go-jose version and run go mod tidy / upgrade to a known-good release.
- If a KeyResponse field was customized, ensure all added fields are JSON-serializable types.
- Read the wrapped %w cause in the error to identify the exact JSON marshal failure and fix the offending field.
- 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
- Keep KeyResponse fields limited to jose.JSONWebKey and serializable types.
- Avoid forked/modified go-jose libraries.
- Check wrapped errors with errors.As to pinpoint offending fields.
- Run unit tests that marshal KeyResponse with representative keys.
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
- error parsing version spec %q
- error encoding version spec: %v
- error building annotation patch: %v
- building node patch: %w
- error building node patch: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/ee649999fd61caac.
Report an issue: GitHub.