Summary
logs() / containerLogs() can return a hydrated resource object instead of raw log text when the log body happens to be valid JSON.
That breaks callers that rely on pod log APIs returning strings, especially when containers intentionally emit structured JSON logs.
Why this is a bug
Kubernetes pods/log is a streamed text endpoint on success.
Relevant Kubernetes source:
pkg/registry/core/pod/rest/log.go declares text/plain and returns a LocationStreamer
staging/src/k8s.io/apiserver/pkg/registry/generic/rest/streamer.go streams the raw response body
So even if a container writes JSON to stdout/stderr, the pod log API still returns raw text. A client library should not hydrate that body into a Kubernetes resource object.
Current behavior
The generic request path now attempts json_decode() for log responses as well. If the body decodes successfully, it hydrates the current resource class.
Because logs() sets the resource class to the current kind, a pod log response that contains valid JSON can be turned into K8sPod instead of being returned as a string.
With native : string return types on logs() / containerLogs(), this can surface as a runtime error like:
TypeError: RenokiCo\PhpK8s\Kinds\K8sResource::logs(): Return value must be of type string, RenokiCo\PhpK8s\Kinds\K8sPod returned
Minimal repro shape
- Call
containerLogs() on a K8sPod
- Have the container emit a JSON object as its log body
- The library decodes the body and hydrates
K8sPod instead of returning the raw string
Expected behavior
Operation::LOG should always return the raw response body as a string before any JSON hydration.
Suggested fix
Restore a dedicated Operation::LOG path so log requests bypass generic JSON hydration.
Equivalent behavior:
if ($operation === Operation::LOG) {
return (string) $response->getBody();
}
Validation
I reproduced this downstream in appwrite-labs/edge, and we patched it in our fork here:
That PR also adds a regression test proving that JSON-looking log payloads are still returned as strings, while normal non-log JSON operations continue to hydrate resources normally.
Summary
logs()/containerLogs()can return a hydrated resource object instead of raw log text when the log body happens to be valid JSON.That breaks callers that rely on pod log APIs returning strings, especially when containers intentionally emit structured JSON logs.
Why this is a bug
Kubernetes
pods/logis a streamed text endpoint on success.Relevant Kubernetes source:
pkg/registry/core/pod/rest/log.godeclarestext/plainand returns aLocationStreamerstaging/src/k8s.io/apiserver/pkg/registry/generic/rest/streamer.gostreams the raw response bodySo even if a container writes JSON to stdout/stderr, the pod log API still returns raw text. A client library should not hydrate that body into a Kubernetes resource object.
Current behavior
The generic request path now attempts
json_decode()for log responses as well. If the body decodes successfully, it hydrates the current resource class.Because
logs()sets the resource class to the current kind, a pod log response that contains valid JSON can be turned intoK8sPodinstead of being returned as a string.With native
: stringreturn types onlogs()/containerLogs(), this can surface as a runtime error like:Minimal repro shape
containerLogs()on aK8sPodK8sPodinstead of returning the raw stringExpected behavior
Operation::LOGshould always return the raw response body as a string before any JSON hydration.Suggested fix
Restore a dedicated
Operation::LOGpath so log requests bypass generic JSON hydration.Equivalent behavior:
Validation
I reproduced this downstream in
appwrite-labs/edge, and we patched it in our fork here:That PR also adds a regression test proving that JSON-looking log payloads are still returned as strings, while normal non-log JSON operations continue to hydrate resources normally.