What
When an upstream answers with a non-2xx and an empty body, the client-visible envelope carries an empty message:
{"error":{"message":"","type":"upstream_error","code":""}}
capture_upstream_error_http (crates/aisix-gateway/src/bridge.rs) builds message from the response body alone, so there is nothing to render when the body is empty. The log line is fine — BridgeError's Display is upstream returned HTTP <status>: — but the caller gets a well-formed error envelope that says nothing.
How it surfaces
Any bodyless upstream error reaches it, but the case that made it visible is a redirect: after #951 an upstream 3xx surfaces as an upstream status instead of being followed, and a 301 with only a Location header is the single most likely bodyless response a provider endpoint returns. A caller then sees a 502 whose message is the empty string, with no hint that the configured endpoint is redirecting.
Suggested fix
Fall back to the status' canonical reason phrase when the body yields no message, e.g. upstream returned 301 Moved Permanently. Deliberately not echoing the Location value: it names a host the operator has not configured, and the gateway does not otherwise expose it.
This changes the rendered message for every empty-bodied upstream error, not only 3xx, which is why it was left out of #951 rather than widened into it.
Size
Small; the renderer is one function and the assertion surface is the error-envelope e2e (error-envelope-normalization-e2e).
Found by the independent pre-merge audit of #951 (LOW-2).
What
When an upstream answers with a non-2xx and an empty body, the client-visible envelope carries an empty message:
{"error":{"message":"","type":"upstream_error","code":""}}capture_upstream_error_http(crates/aisix-gateway/src/bridge.rs) buildsmessagefrom the response body alone, so there is nothing to render when the body is empty. The log line is fine —BridgeError'sDisplayisupstream returned HTTP <status>:— but the caller gets a well-formed error envelope that says nothing.How it surfaces
Any bodyless upstream error reaches it, but the case that made it visible is a redirect: after #951 an upstream 3xx surfaces as an upstream status instead of being followed, and a
301with only aLocationheader is the single most likely bodyless response a provider endpoint returns. A caller then sees a 502 whose message is the empty string, with no hint that the configured endpoint is redirecting.Suggested fix
Fall back to the status' canonical reason phrase when the body yields no message, e.g.
upstream returned 301 Moved Permanently. Deliberately not echoing theLocationvalue: it names a host the operator has not configured, and the gateway does not otherwise expose it.This changes the rendered message for every empty-bodied upstream error, not only 3xx, which is why it was left out of #951 rather than widened into it.
Size
Small; the renderer is one function and the assertion surface is the error-envelope e2e (
error-envelope-normalization-e2e).Found by the independent pre-merge audit of #951 (LOW-2).