kubernetes/kops · error

error parsing %q: %v

Error message

error parsing %q: %v

What it means

ParseZoneRules wraps an error returned by ParseZoneSpec for an individual --zone argument, prefixing it with the offending string. ParseZoneSpec itself is very lenient (it splits on '/'), so this fires when the wrapped ParseZoneSpec returns an error — meaning the entry could not be converted into a ZoneSpec, effectively a malformed zone rule in the controller's --zone flags.

Source

Thrown at dns-controller/pkg/dns/zonespec.go:68

type ZoneRules struct {
	// We don't use a map so we can support e.g. *.example.com later
	Zones    []*ZoneSpec
	Wildcard bool
}

func ParseZoneRules(zones []string) (*ZoneRules, error) {
	r := &ZoneRules{}

	for _, s := range zones {
		s = strings.TrimSpace(s)
		if s == "*" || s == "*/*" {
			r.Wildcard = true
			continue
		}

		zoneSpec, err := ParseZoneSpec(s)
		if err != nil {
			return nil, fmt.Errorf("error parsing %q: %v", s, err)
		}

		r.Zones = append(r.Zones, zoneSpec)
	}

	if len(zones) == 0 {
		klog.Infof("No rules specified, will permit management of all zones")
		r.Wildcard = true
	}

	return r, nil
}

// MatchesExplicitly returns true if this matches an explicit rule (not a wildcard)
func (r *ZoneRules) MatchesExplicitly(zone dnsprovider.Zone) bool {
	name := EnsureDotSuffix(zone.Name())
	id := zone.ID()

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Log/inspect the quoted string in the error to find the offending --zone value
  2. Correct the flag value to a supported form: example.com, */ZONE_ID, or example.com/ZONE_ID
  3. Trim whitespace / empty entries from the flag list before starting the controller
  4. Add a unit test covering the malformed spec via TestParseZoneRules

Example fix

// before
--zone="" --zone=example.com
// after
--zone=example.com  # or */Z1234 or example.com/Z1234
Defensive patterns

Strategy: validation

Validate before calling

// validate --zone flags before starting the controller
for _, z := range zoneFlags {
    z = strings.TrimSpace(z)
    if z == "" { return fmt.Errorf("empty --zone entry") }
    if strings.HasPrefix(z, "/") { return fmt.Errorf("invalid zone spec %q: missing name before '/'", z) }
    parts := strings.Split(z, "/")
    if len(parts) > 2 { return fmt.Errorf("invalid zone spec %q: too many '/'", z) }
}

Try / catch

rules, err := dns.ParseZoneRules(zones)
if err != nil {
    klog.Fatalf("invalid --zone flags: %v", err) // error quotes the bad entry
}

Prevention

When it happens

Trigger: main() calls ParseZoneRules(strings from --zone flags) and one of the strings causes ParseZoneSpec to error; also hit directly in unit tests (TestParseZoneRules) feeding malformed specs.

Common situations: Malformed --zone flag values (e.g. empty string or unexpected format) passed on the dns-controller command line; mis-templated flag values in manifests/Helm charts producing blank entries; typos like '/1234' with an empty name.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/a12edea9724693e6. Report an issue: GitHub.