cilium/cilium · error

failed to unmarshal json: %w

Error message

failed to unmarshal json: %w

What it means

Shared JSON parser for feature-metrics output: `json.Unmarshal([]byte(output), &encStatus)` into []*models.Metric failed. Any caller (agent or operator fetch) surfaces this wrapped error when the command output is not the expected JSON metric array.

Source

Thrown at cilium-cli/features/status.go:367

}

func ciliumOperatorBinary(pod corev1.Pod) string {
	for _, container := range pod.Spec.Containers {
		if container.Name == defaults.OperatorContainerName {
			for _, cmd := range container.Command {
				if strings.Contains(cmd, "cilium-operator") {
					return cmd
				}
			}
		}
	}
	return ""
}

func nodeStatusFromOutput(output string) ([]*models.Metric, error) {
	var encStatus []*models.Metric
	if err := json.Unmarshal([]byte(output), &encStatus); err != nil {
		return []*models.Metric{}, fmt.Errorf("failed to unmarshal json: %w", err)
	}
	return encStatus, nil
}

type statusPrinter interface {
	printHeader(sorted []string) error
	printNode(metricName, labels string, isBinary bool, values map[float64]struct{}, key string, nodesSorted []string, metricsPerNode map[string]map[string]float64)
	end() error
}

// parseNameAndLabels splits the key into name and labels based on the first ";" separator
func parseNameAndLabels(key string) (string, string) {
	if before, after, found := strings.Cut(key, ";"); found {
		return before, after
	}
	return key, ""
}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Run the same command manually with `kubectl exec` and confirm it emits a JSON array
  2. Fix the container/binary selection so the real cilium binary runs
  3. Align cilium-cli and Cilium versions so the JSON schema matches models.Metric
  4. Callers should catch this and fall back to skipping metrics collection for that node

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

if strings.TrimSpace(output) == "" {
	return errors.New("empty metrics output; cannot unmarshal")
}

Type guard

func parsesAsMetrics(output string) ([]*models.Metric, bool) {
	var m []*models.Metric
	err := json.Unmarshal([]byte(output), &m)
	return m, err == nil
}

Try / catch

enc, err := nodeStatusFromOutput(out)
if err != nil {
	var uerr *json.UnmarshalTypeError
	if errors.As(err, &uerr) {
		log.Printf("schema mismatch at offset %d: %v", uerr.Offset, uerr)
	}
	return degradeGracefully()
}

Prevention

When it happens

Trigger: Output of the in-pod command contains non-JSON content — command-not-found usage text, log lines, truncated output, or empty string — so Unmarshal fails.

Common situations: Wrong container command produced help/usage text; pod output buffer truncated; Cilium version emits a different JSON schema than models.Metric.

Related errors


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