Summary
The AuthBridge injection webhook (inject.rossoctl.io, rossoctl-operator 0.3.0-rc.1) injects the lowercase no_proxy env var into the agent container with an embedded literal newline + indentation (\n ) in the middle of the value. Because the agent's HTTP client is httpx (which reads no_proxy via trust_env), httpx rejects the value and every outbound request from the agent fails before it leaves the pod — including MCP tool calls and LLM calls.
Symptom (user-facing)
Weather-agent chat fails with:
Error: Cannot connect to MCP weather service at
http://weather-tool-mcp.team1.svc.cluster.local:8000/mcp.
Please ensure the weather MCP server is running.
Error: Invalid non-printable ASCII character in URL, '\n' at position 37.
The MCP tool is actually healthy (returns 401 missing Authorization header to an unauthenticated probe) — the failure is purely client-side URL/proxy parsing.
Root cause
Inside the running agent container, os.environ['no_proxy'] (lowercase) contains a stray newline:
no_proxy = '...,otel-collector.rossoctl-system\n .svc.cluster.local,keycloak.keycloak.svc.cluster.local'
# ^^^^ literal "\n " (newline + 2 spaces)
httpx's trust_env proxy handling parses no_proxy, and the \n triggers
httpx.InvalidURL: Invalid non-printable ASCII character in URL, '\n' at position 37
when it builds its proxy mounts. The uppercase NO_PROXY is clean, but httpx reads the
lowercase variant too, so it still fails.
The \n (newline + two spaces) is characteristic of a YAML block-scalar / multi-line
template join in the operator's env-composition code — the base no-proxy list and the
appended cluster hosts (.svc.cluster.local,keycloak.keycloak.svc.cluster.local) are being
concatenated with a newline instead of a comma.
Environment
- Operator:
ghcr.io/rossoctl/operator/rossoctl-operator:0.3.0-rc.1
- Webhook:
rossoctl-operator-chart-mutating-webhook-configuration → inject.rossoctl.io
- Cluster: OpenShift (HyperShift hosted), Istio ambient
- Injected container:
agent (alongside the authbridge-proxy sidecar)
Reproduction
- Deploy any agent that gets the AuthBridge sidecar injected (e.g. weather-service in
team1).
kubectl exec <agent-pod> -c agent -- /app/.venv/bin/python -c "import os; print(repr(os.environ['no_proxy']))"
- Observe the embedded
\n in the value.
- Any httpx call from the agent (MCP tool, LLM) fails with the
InvalidURL error above.
Expected
The injected no_proxy/NO_PROXY must be a single-line, comma-separated string with no
newlines or embedded whitespace between entries.
Workaround (applied manually)
Override the env on the deployment with a clean single-line value; it survives webhook
re-injection because the container already defines the var:
CLEAN='127.0.0.1,localhost,<external-llm-host>,.svc,.svc.cluster.local,.cluster.local,<tool-host>,keycloak.keycloak.svc.cluster.local,otel-collector.rossoctl-system'
kubectl set env deployment/<agent> -n <ns> -c agent no_proxy="$CLEAN" NO_PROXY="$CLEAN"
Suggested fix
In the operator's proxy-env composition, join no-proxy entries with , and never emit a
YAML block scalar / newline. Add a guard/test asserting the composed value matches
^[^\s]+(,[^\s]+)*$ (no whitespace) before setting it on the container.
Related
Assisted-By: Claude Code
Summary
The AuthBridge injection webhook (
inject.rossoctl.io, rossoctl-operator0.3.0-rc.1) injects the lowercaseno_proxyenv var into the agent container with an embedded literal newline + indentation (\n) in the middle of the value. Because the agent's HTTP client is httpx (which readsno_proxyviatrust_env), httpx rejects the value and every outbound request from the agent fails before it leaves the pod — including MCP tool calls and LLM calls.Symptom (user-facing)
Weather-agent chat fails with:
The MCP tool is actually healthy (returns
401 missing Authorization headerto an unauthenticated probe) — the failure is purely client-side URL/proxy parsing.Root cause
Inside the running agent container,
os.environ['no_proxy'](lowercase) contains a stray newline:httpx's
trust_envproxy handling parsesno_proxy, and the\ntriggershttpx.InvalidURL: Invalid non-printable ASCII character in URL, '\n' at position 37when it builds its proxy mounts. The uppercase
NO_PROXYis clean, but httpx reads thelowercase variant too, so it still fails.
The
\n(newline + two spaces) is characteristic of a YAML block-scalar / multi-linetemplate join in the operator's env-composition code — the base no-proxy list and the
appended cluster hosts (
.svc.cluster.local,keycloak.keycloak.svc.cluster.local) are beingconcatenated with a newline instead of a comma.
Environment
ghcr.io/rossoctl/operator/rossoctl-operator:0.3.0-rc.1rossoctl-operator-chart-mutating-webhook-configuration→inject.rossoctl.ioagent(alongside theauthbridge-proxysidecar)Reproduction
team1).kubectl exec <agent-pod> -c agent -- /app/.venv/bin/python -c "import os; print(repr(os.environ['no_proxy']))"\nin the value.InvalidURLerror above.Expected
The injected
no_proxy/NO_PROXYmust be a single-line, comma-separated string with nonewlines or embedded whitespace between entries.
Workaround (applied manually)
Override the env on the deployment with a clean single-line value; it survives webhook
re-injection because the container already defines the var:
Suggested fix
In the operator's proxy-env composition, join no-proxy entries with
,and never emit aYAML block scalar / newline. Add a guard/test asserting the composed value matches
^[^\s]+(,[^\s]+)*$(no whitespace) before setting it on the container.Related
(over-restriction vs. malformed value). Fixing both in the composition code makes sense.
Assisted-By: Claude Code