kubernetes/kops · error
cannot decode GCE label: %q
Error message
cannot decode GCE label: %q
What it means
DecodeGCELabel reverses EncodeGCELabel, which URI-escapes non [0-9a-z] bytes with '-' instead of '%'. Decoding turns '-' back into '%' and calls url.QueryUnescape; if that fails (e.g. a trailing or lone '%' after replacement, or an invalid hex escape like %G1), the function wraps the input string in this error. It signals that the label value was not produced by EncodeGCELabel or has been corrupted.
Source
Thrown at upup/pkg/fi/cloudup/gce/labels.go:64
c := s[i]
if ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') {
b.WriteByte(c)
} else {
b.WriteByte('-')
b.WriteByte("0123456789abcdef"[c>>4])
b.WriteByte("0123456789abcdef"[c&15])
}
}
return b.String()
}
// DecodeGCELabel reverse EncodeGCELabel, taking the encoded RFC1035 compatible value back to a string
func DecodeGCELabel(s string) (string, error) {
uriForm := strings.ReplaceAll(s, "-", "%")
v, err := url.QueryUnescape(uriForm)
if err != nil {
return "", fmt.Errorf("cannot decode GCE label: %q", s)
}
return v, nil
}
// TagForRole return the instance (network) tag used for instances with the given role.
func TagForRole(clusterName string, role kops.InstanceGroupRole) string {
return ClusterPrefixedName(GceLabelNameRolePrefix+role.ToLowerString(), clusterName, 63)
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Ensure every label was written via EncodeGCELabel; re-encode any manually-set labels or let kops recreate them
- Inspect the failing label string: any '-' must decode to '%XX' with two valid hex digits; fix or remove invalid '-' sequences
- If labels came from an older kops version, upgrade kops and run 'kops update cluster' to re-stamp labels
- Wrap decode failures and skip/log the offending label instead of failing the whole etcd status scan
Example fix
// before
v, err := url.QueryUnescape(uriForm)
if err != nil {
return "", fmt.Errorf("cannot decode GCE label: %q", s)
}
// after
// only attempt decode for kops-encoded labels; otherwise return as-is
if !strings.Contains(s, "-") {
return s, nil
}
v, err := url.QueryUnescape(uriForm)
if err != nil {
return "", fmt.Errorf("cannot decode GCE label: %q", s)
} Defensive patterns
Strategy: validation
Validate before calling
func isDecodableGCELabel(s string) bool {
uriForm := strings.ReplaceAll(s, "-", "%")
_, err := url.QueryUnescape(uriForm)
return err == nil
}
if !isDecodableGCELabel(label) { log.Warnf("skipping non-kops label %q", label); return } Type guard
func isKopsEncodedLabel(s string) bool {
// every '-' must be followed by two hex digits (from EncodeGCELabel escaping)
for i := 0; i < len(s); i++ {
if s[i] == '-' && (i+2 >= len(s) || !isHex(s[i+1]) || !isHex(s[i+2])) {
return false
}
}
return true
} Try / catch
decoded, err := gce.DecodeGCELabel(label)
if err != nil {
// treat as foreign/corrupt label: skip rather than fail the scan
klog.V(2).Infof("ignoring undecodable label %q: %v", label, err)
continue
} Prevention
- Only ever write GCE labels through EncodeGCELabel, never manually in the console
- Reject instance group / label inputs containing characters outside RFC1035-safe sets at spec-validation time
- When scanning labels, skip-and-log labels that fail decode instead of aborting
- Add unit tests mixing hand-written labels to ensure decode is only attempted for encoded values
When it happens
Trigger: A GCE label value containing '-' that was created manually or by another tool (kops-generated labels always encode literal '-' as '--2d', so a lone '-' decodes to '%2d' and is fine only when followed by two hex digits). Passing a raw '-'-containing string like 'my-label' yields '%2d' which is valid, but 'abc%-' or a string with a single trailing '-' producing an incomplete percent-escape (e.g. 'x-1' -> 'x%1') fails QueryUnescape and triggers this error. Called from findEtcdStatus when reading etcd cluster status labels off GCE instances.
Common situations: Manually editing GCE labels in the cloud console; labels created by other controllers or older kops versions with different encoding; hand-crafting instance group names/labels with characters that produce invalid escapes; copied/mangled label strings in scripts.
Related errors
- error setting labels on created Disk: %v
- reading created ForwardingRule %q: %v
- setting ForwardingRule labels: %w
- setting ForwardRule labels: %w
- error encoding version spec: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/9dd88aac140137aa.
Report an issue: GitHub.