derailed/k9s · error
data section in secret description is invalid
Error message
data section in secret description is invalid
What it means
Thrown by Secret.Decode after the '====' separator was found but the description ends immediately after it (dataEndIndex+4 >= len(encodedDescription)). That means the describe body is truncated exactly at the separator, leaving no text after the marker to keep as the decoded section's prefix. The parser treats this as a malformed data section and refuses to guess.
Source
Thrown at internal/dao/secret.go:99
return buff.String(), nil
}
// SetDecodeData toggles decode mode.
func (s *Secret) SetDecodeData(b bool) {
s.decodeData = b
}
// Decode removes the encoded part from the secret's description and appends the
// secret's decoded data.
func (s *Secret) Decode(encodedDescription, path string) (string, error) {
dataEndIndex := strings.Index(encodedDescription, "====")
if dataEndIndex == -1 {
return "", fmt.Errorf("unable to find data section in secret description")
}
dataEndIndex += 4
if dataEndIndex >= len(encodedDescription) {
return "", fmt.Errorf("data section in secret description is invalid")
}
// Remove the encoded part from k8s's describe API
// More details about the reasoning of index: https://github.com/kubernetes/kubectl/blob/v0.29.0/pkg/describe/describe.go#L2542
body := encodedDescription[0:dataEndIndex]
o, err := s.Get(context.Background(), path)
if err != nil {
return "", err
}
data, err := ExtractSecrets(o)
if err != nil {
return "", err
}
decodedSecrets := make([]string, 0, len(data))
for _, k := range slices.Sorted(maps.Keys(data)) {
line := fmt.Sprintf("%s: %s", k, data[k])
decodedSecrets = append(decodedSecrets, strings.TrimSpace(line))View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Confirm the Secret has data keys: kubectl get secret <name> -o jsonpath='{.data}' should not be empty
- Inspect kubectl describe secret <name> output and check content exists after the '====' line
- Re-run describe: a truncated response can be transient when the API server is under load
- Match k9s version to your cluster's kubectl describe format, or fall back to kubectl get secret -o yaml
Defensive patterns
Strategy: fallback
Validate before calling
dataEnd := strings.Index(desc, "====")
if dataEnd == -1 || dataEnd+4 >= len(desc) {
return desc, nil // no usable data section; use raw description
}
decoded, err := s.Decode(desc, path) Try / catch
if decoded, err := s.Decode(desc, path); err != nil {
slog.Warn("secret decode failed; falling back", slogs.Error, err)
return desc, nil
} else {
return decoded, nil
} Prevention
- Treat an empty secret .data map as 'nothing to decode' and skip Decode entirely
- Never feed truncated describe strings into Decode; pass the full API response
When it happens
Trigger: Decode() is called on describe output where '====' is the last four characters: an empty Data section rendered as only the marker line, a truncated describe response from the API server, or describe output generated by a tool that appends the separator without the following content.
Common situations: Empty Secrets (no .data keys) on clusters whose describer still prints the '====' trailer; piping partial describe output into the decoder; version skew between the kubectl describe format k9s expects and what the cluster emits.
Related errors
- unable to find data section in secret description
- failed to decode table rows: %w
- expected Unstructured, but got %T
- node is cordoned
- namespace not ready
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/87c78ca4caace069.
Report an issue: GitHub.