grpc/grpc-go · error

rls_csp: error marshaling load balancing config

Error message

rls_csp: error marshaling load balancing config %v: %v

What it means

The internally constructed lbConfigJSON struct could not be serialized via encoding/json.Marshal (rls.go:81-83). The struct contains a json.RawMessage field (RouteLookupConfig bytes from protojson), so a marshal failure means those bytes are not valid JSON.

Solutions

  1. This is likely a google.golang.org/protobuf library bug — report it with the RouteLookupConfig proto that triggered it
  2. Check for outdated or mismatched google.golang.org/protobuf versions in go.mod
  3. Inspect the lbCfgJSON.RouteLookupConfig bytes for anomalies
Defensive patterns

Strategy: validation

Validate before calling

// Validate that protojson output is valid JSON before re-marshaling.
if !json.Valid(rlcJSON) {
    return fmt.Errorf("protojson produced invalid JSON for RouteLookupConfig")
}

Prevention

When it happens

Trigger: json.Marshal(lbCfgJSON) fails because the RouteLookupConfig json.RawMessage produced by the preceding protojson.Marshal contains bytes that encoding/json rejects as invalid JSON.

Common situations: Extremely rare — protojson.Marshal succeeded but produced output that encoding/json considers invalid; indicates a bug in the protobuf library or corrupted proto state. Effectively an internal/library error rather than a configuration issue.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/eeae4e1a1dca9459. Report an issue: GitHub.

Appendix: source

Thrown at internal/xds/clusterspecifier/rls/rls.go:83

		return nil, fmt.Errorf("rls_csp: error parsing config %v: %v", cfg, err)
	}
	rlcJSON, err := protojson.Marshal(rlcs.GetRouteLookupConfig())
	if err != nil {
		return nil, fmt.Errorf("rls_csp: error marshaling route lookup config: %v: %v", rlcs.GetRouteLookupConfig(), err)
	}
	lbCfgJSON := &lbConfigJSON{
		RouteLookupConfig: rlcJSON, // "JSON form of RouteLookupClusterSpecifier.config" - RLS in xDS Design Doc
		ChildPolicy: []map[string]json.RawMessage{
			{
				"cds_experimental": json.RawMessage(`{"isDynamic":true}`),
			},
		},
		ChildPolicyConfigTargetFieldName: "cluster",
	}

	rawJSON, err := json.Marshal(lbCfgJSON)
	if err != nil {
		return nil, fmt.Errorf("rls_csp: error marshaling load balancing config %v: %v", lbCfgJSON, err)
	}

	rlsBB := balancer.Get(internal.RLSLoadBalancingPolicyName)
	if rlsBB == nil {
		return nil, fmt.Errorf("RLS LB policy not registered")
	}
	if _, err = rlsBB.(balancer.ConfigParser).ParseConfig(rawJSON); err != nil {
		return nil, fmt.Errorf("rls_csp: validation error from rls lb policy parsing: %v", err)
	}

	return clusterspecifier.BalancerConfig{{internal.RLSLoadBalancingPolicyName: lbCfgJSON}}, nil
}

View on GitHub (pinned to 0c51461d27)