What happened:
kubectl explain <type>.<invalid-field> still prints the KIND/VERSION header to stdout before it fails. The error itself goes to stderr and the exit code is 1, but stdout isn't empty, so a failed command still produces output that looks like a real result.
What you expected to happen:
A command that fails shouldn't write anything to stdout. Scripts treat stdout as the result, so the leftover header ends up in redirects, pipes, and $(...) as if the command had worked. On failure, only the stderr message and the non-zero exit code should show up.
How to reproduce it (as minimally and precisely as possible):
# stdout is non-empty even though the command fails:
$ kubectl explain pods.spec.nonexistentfield 2>/dev/null; echo "exit=$?"
KIND: Pod
VERSION: v1
exit=1
# same with --recursive:
$ kubectl explain pods.spec.nonexistentfield --recursive 2>/dev/null; echo "exit=$?"
KIND: Pod
VERSION: v1
exit=1
An invalid top-level type doesn't have this problem; it fails before rendering, so stdout stays empty:
$ kubectl explain nosuchresource 2>/dev/null; echo "exit=$?"
exit=1
Anything else we need to know?:
The explain v2 renderer writes the template straight to the output writer. The KIND/VERSION header (in pkg/explain/v2/templates/plaintext.tmpl) is written before the field path is walked, and the "field does not exist" error only fires partway through rendering, so by then the header is already on stdout.
Environment:
- Kubernetes client and server versions (use
kubectl version): Client v1.36.1 (also reproduces on master, v1.38.0-alpha.0); server v1.36.1
- Cloud provider or hardware configuration: kind
- OS (e.g:
cat /etc/os-release): macOS, but it's not platform-specific
What happened:
kubectl explain <type>.<invalid-field>still prints theKIND/VERSIONheader to stdout before it fails. The error itself goes to stderr and the exit code is 1, but stdout isn't empty, so a failed command still produces output that looks like a real result.What you expected to happen:
A command that fails shouldn't write anything to stdout. Scripts treat stdout as the result, so the leftover header ends up in redirects, pipes, and
$(...)as if the command had worked. On failure, only the stderr message and the non-zero exit code should show up.How to reproduce it (as minimally and precisely as possible):
An invalid top-level type doesn't have this problem; it fails before rendering, so stdout stays empty:
Anything else we need to know?:
The explain v2 renderer writes the template straight to the output writer. The
KIND/VERSIONheader (inpkg/explain/v2/templates/plaintext.tmpl) is written before the field path is walked, and the "field does not exist" error only fires partway through rendering, so by then the header is already on stdout.Environment:
kubectl version): Client v1.36.1 (also reproduces on master, v1.38.0-alpha.0); server v1.36.1cat /etc/os-release): macOS, but it's not platform-specific