Summary
When the gateway is unreachable, openclaw agent silently falls back to embedded mode and writes a single line to stderr that's easy to miss. There's no banner on stdout, no exit-code change, and the JSON result looks superficially like a normal gateway response. Operators who don't tail .err will believe a gateway-side run happened when it didn't.
Reproduction
- Stop the gateway (e.g. kill the
openclaw-gateway process inside the container, or unset its port).
- Run any
openclaw agent invocation.
- Inspect stdout vs. stderr.
Observed behaviour
stdout (the --json payload) contains a normal-looking run result. stderr contains exactly:
Gateway agent failed; falling back to embedded: Error: gateway closed (1006 abnormal closure (no close frame)): no close reason
Exit code is 0. The result is not the same as a gateway run (no telemetry/observability spans land in the otel pipeline, sub-agent context can differ, tool registries may differ).
Expected behaviour
At least one of:
- Print a clearly-marked banner on stdout (e.g.
⚠ EMBEDDED FALLBACK — gateway unreachable) before the JSON payload.
- Emit a
meta.transport: "embedded" field in the JSON result so downstream consumers can detect.
- Exit non-zero unless
--allow-embedded-fallback is passed (opt-in, not opt-out).
Why this matters
Embedded vs. gateway runs diverge on observability (no OTel spans), on tool/plugin loadout, and on session-state semantics. Silent fallback creates a class of "I thought I tested X but I tested embedded-X" bugs that are very hard to diagnose. We hit this in our 2026-04-25 retest after the gateway crashed (separately filed).
Environment
OpenClaw 2026.4.12 (1c0672b).
Summary
When the gateway is unreachable,
openclaw agentsilently falls back to embedded mode and writes a single line tostderrthat's easy to miss. There's no banner onstdout, no exit-code change, and the JSONresultlooks superficially like a normal gateway response. Operators who don'ttail .errwill believe a gateway-side run happened when it didn't.Reproduction
openclaw-gatewayprocess inside the container, or unset its port).openclaw agentinvocation.Observed behaviour
stdout(the--jsonpayload) contains a normal-looking run result.stderrcontains exactly:Exit code is 0. The result is not the same as a gateway run (no telemetry/observability spans land in the otel pipeline, sub-agent context can differ, tool registries may differ).
Expected behaviour
At least one of:
⚠ EMBEDDED FALLBACK — gateway unreachable) before the JSON payload.meta.transport: "embedded"field in the JSON result so downstream consumers can detect.--allow-embedded-fallbackis passed (opt-in, not opt-out).Why this matters
Embedded vs. gateway runs diverge on observability (no OTel spans), on tool/plugin loadout, and on session-state semantics. Silent fallback creates a class of "I thought I tested X but I tested embedded-X" bugs that are very hard to diagnose. We hit this in our 2026-04-25 retest after the gateway crashed (separately filed).
Environment
OpenClaw 2026.4.12 (
1c0672b).