grpc/grpc-go · error

rls: childPolicyConfigTargetFieldName field is not set in se

Error message

rls: childPolicyConfigTargetFieldName field is not set in service config %+v

What it means

Returned by rls.ParseConfig (config.go:173-175) when ChildPolicyConfigTargetFieldName is empty. RLS swaps the target field of its child policy config with each looked-up target, so it must know which field name to overwrite (e.g. "target" for pick_first, "endpoint" in xDS). An empty value makes target substitution impossible, so it is required.

Source

Thrown at balancer/rls/config.go:174

	rlsProto := &rlspb.RouteLookupConfig{}
	if err := m.Unmarshal(cfgJSON.RouteLookupConfig, rlsProto); err != nil {
		return nil, fmt.Errorf("rls: bad RouteLookupConfig proto %+v: %v", string(cfgJSON.RouteLookupConfig), err)
	}
	lbCfg, err := parseRLSProto(rlsProto)
	if err != nil {
		return nil, err
	}

	if sc := string(cfgJSON.RouteLookupChannelServiceConfig); sc != "" {
		parsed := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(sc)
		if parsed.Err != nil {
			return nil, fmt.Errorf("rls: bad control channel service config %q: %v", sc, parsed.Err)
		}
		lbCfg.controlChannelServiceConfig = sc
	}

	if cfgJSON.ChildPolicyConfigTargetFieldName == "" {
		return nil, fmt.Errorf("rls: childPolicyConfigTargetFieldName field is not set in service config %+v", string(c))
	}
	name, config, err := parseChildPolicyConfigs(cfgJSON.ChildPolicy, cfgJSON.ChildPolicyConfigTargetFieldName)
	if err != nil {
		return nil, err
	}
	lbCfg.childPolicyName = name
	lbCfg.childPolicyConfig = config
	lbCfg.childPolicyTargetField = cfgJSON.ChildPolicyConfigTargetFieldName
	return lbCfg, nil
}

func parseRLSProto(rlsProto *rlspb.RouteLookupConfig) (*lbConfig, error) {
	// Validations specified on the `grpc_keybuilders` field are performed here.
	kbMap, err := keys.MakeBuilderMap(rlsProto)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Set childPolicyConfigTargetFieldName to the target field name expected by the chosen child policy (commonly "target" for pick_first/round_robin-style policies).
  2. Ensure the value matches the field name your child policy uses to receive its address/target.

Example fix

// before
cfg.ChildPolicyConfigTargetFieldName = ""

// after
cfg.ChildPolicyConfigTargetFieldName = "target"
Defensive patterns

Strategy: validation

Validate before calling

func validateTargetFieldName(cfg map[string]any) error {
    v, _ := cfg["childPolicyConfigTargetFieldName"].(string)
    if v == "" {
        return errors.New("childPolicyConfigTargetFieldName must be set")
    }
    return nil
}

Type guard

func hasTargetFieldName(cfg map[string]any) bool {
    v, _ := cfg["childPolicyConfigTargetFieldName"].(string)
    return v != ""
}

Prevention

When it happens

Trigger: The RLS service config omits childPolicyConfigTargetFieldName, or sets it to "".

Common situations: Hand-writing RLS config and forgetting the field. Control plane not populating it because the child policy type is ambiguous.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/8b3db3de42a7c8ed. Report an issue: GitHub.