cilium/cilium · error

CEC JSON decoding paniced: %v

Error message

CEC JSON decoding paniced: %v

What it means

XDSResource.UnmarshalJSON in pkg/k8s/apis/cilium.io/v2/cec_types.go decodes CiliumEnvoyConfig xDS resources with protojson.Unmarshal into an anypb.Any. Since protojson can panic on malformed input, a deferred recover converts any panic into this 'CEC JSON decoding paniced: %v' error so the K8s decode path does not crash the process.

Source

Thrown at pkg/k8s/apis/cilium.io/v2/cec_types.go:178

// DeepEqual returns 'true' if 'a' and 'b' are equal.
func (a *XDSResource) DeepEqual(b *XDSResource) bool {
	return proto.Equal(a.Any, b.Any)
}

// MarshalJSON ensures that the unstructured object produces proper
// JSON when passed to Go's standard JSON library.
func (u *XDSResource) MarshalJSON() ([]byte, error) {
	return protojson.Marshal(u.Any)
}

// UnmarshalJSON ensures that the unstructured object properly decodes
// JSON when passed to Go's standard JSON library.
func (u *XDSResource) UnmarshalJSON(b []byte) (err error) {
	// xDS resources are not validated in K8s, recover from possible panics
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("CEC JSON decoding paniced: %v", r)
		}
	}()
	u.Any = &anypb.Any{}
	err = protojson.Unmarshal(b, u.Any)
	if err != nil {
		var buf bytes.Buffer
		json.Indent(&buf, b, "", "\t")
		// slogloggercheck: it's safe to use the default logger here as it has been initialized by the program up to this point.
		logging.DefaultSlogLogger.Warn("Ignoring invalid CiliumEnvoyConfig JSON",
			logfields.Error, err,
			logfields.Object, buf,
		)
	} else if option.Config.Debug {
		// slogloggercheck: it's safe to use the default logger here as it has been initialized by the program up to this point.
		logging.DefaultSlogLogger.Debug("CEC unmarshaled XDS Resource", logfields.Resource, prototext.Format(u.Any))
	}
	return nil
}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Validate the xds resource payload is proper protobuf JSON with a correct '@type' fully-qualified Any type name (e.g. type.googleapis.com/envoy.config...)
  2. Compare against a known-good CEC example from the cilium repo for your version and fix field names/types
  3. Convert the Envoy config using protoc/gogo protojson marshaling instead of hand-writing JSON
  4. Check cilium version compatibility of the resource schema and update the CEC accordingly

Example fix

// before
resources:
- "@type": envoy.config.filter...  # wrong/abbreviated type
// after
resources:
- "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  ...
Defensive patterns

Strategy: validation

Validate before calling

// validate the Any payload before creating the CEC
var anyObj map[string]any
if err := json.Unmarshal(xdsBytes, &anyObj); err != nil { return err }
t, ok := anyObj["@type"]
if !ok || !strings.HasPrefix(t.(string), "type.googleapis.com/") {
    return fmt.Errorf("xds resource missing valid @type")
}

Type guard

func hasValidAnyType(b []byte) bool {
    var m struct{ Type string `json:"@type"` }
    return json.Unmarshal(b, &m) == nil && strings.HasPrefix(m.Type, "type.googleapis.com/")
}

Try / catch

if err := json.Unmarshal(rawCEC, &cec); err != nil {
    if strings.HasPrefix(err.Error(), "CEC JSON decoding paniced") {
        // reject resource, log payload, fix @type/protobuf-JSON
    }
}

Prevention

When it happens

Trigger: A CiliumEnvoyConfig (CEC) resource is applied whose xds resource bytes are not valid protobuf JSON for anypb.Any (e.g. '@type' missing/incorrect, invalid field types), causing protojson to panic during UnmarshalJSON.

Common situations: Hand-writing CEC YAML/JSON with a wrong or missing @type in the Any payload; copy-pasted Envoy config that is plain Envoy JSON rather than protobuf-JSON; version mismatch where a field was renamed.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/c0f6553d4fc1611d. Report an issue: GitHub.