ValueError aborted the whole GatewayConfigSchema, taking every channel offline. Now the schema returns an empty token for the unavailable credential, the runtime’s pre-existing “no token → skip” path isolates that one channel, and health() reports it as degraded.
This is a resilience contract, not a new API. Nothing changes in how you write
gateway.yaml — the same Secret References you already use now fail open per-channel instead of failing closed for the whole gateway.What Changed
A single channel’s unavailable credential is isolated; structural errors and the gateway’s own ingress secret still fail closed.
The single most important distinction: a channel credential fails open (isolated, degraded); the gateway’s own config and ingress secret fail closed (abort).
How to Observe the Degraded State
The degraded channel is visible in the startup log,gateway doctor, channels --probe, and GET /health — no value is ever printed.
Startup log
One redacted WARNING is logged per degraded channel. An unset${ENV} token logs:
{source, id} reference that resolves to configured-but-unavailable / missing logs:
praisonai gateway doctor
The secrets block reports configured-but-unavailable or missing for the affected field.
praisonai gateway channels --probe
The channel listing surfaces the same per-channel verdict — a one-line probe you can run against a live gateway.
GET /health on the running gateway
The degraded channel appears under channels, distinguished from a running channel by status: "degraded" and a reason.
health() — it does not silently vanish, so a monitor can tell “configured-but-unavailable” apart from “never configured”.
The same shape is used whether the credential was unavailable at boot or rejected at runtime — an operator dashboard doesn’t need two code paths. A runtime-rejected channel adds a
supervision block with state: "credential-unavailable"; see Runtime credential rejection.How to Recover
1
Fix the credential
Rotate the env var, refill the mounted secret file, or restore the secret manager so the token resolves to
available again.2
Reload the config
An empty credential is resolved once at config load, so
praisonai gateway reconnect <channel> alone does not re-read it — reconnect drives the channel supervisor, not the secret resolver. Trigger a config reload (or restart) so the schema re-resolves the now-available token. See Channel Supervision for reconnect/pause/resume.3
Confirm it recovered
On the next config load, a channel that previously degraded but now has a token is removed from the degraded set automatically. Verify with
praisonai gateway doctor or GET /health.For a token that was rejected at runtime (rather than empty at boot),
praisonai gateway reconnect <channel> is enough on env-var-backed tokens — the supervisor wakes the parked channel and Bot.start() re-resolves the env var. A full config hot-reload is required only when the token lives in a {source: file, id: …} reference that was rewritten on disk while the channel was parked.Gateway Hot Reload picks the new credential up without a full restart — the reload re-resolves every channel’s secret and drops recovered channels out of the degraded set.
When You Do NOT Want This Behaviour
Some operators prefer strict fail-closed — enforce it at the operator layer, not the schema. Preflight (--preflight, the default) still hard-aborts on a credential failure at start. The isolation contract only matters after the gateway is already running, or when preflight was explicitly skipped with --no-preflight.
There is intentionally no knob to make the schema raise again — that behaviour was removed precisely because it took healthy channels down. To gate a deploy on strict availability, fail the release if praisonai gateway doctor --json reports any configured-but-unavailable or missing:
Best Practices
Gate deploys on praisonai gateway doctor --json
Gate deploys on praisonai gateway doctor --json
Read the
secrets block and fail the deploy if any field is not available (or configured for exec sources). This gives you strict fail-closed at release time while keeping the resilient fail-open behaviour at runtime.Use {source: file} for K8s / Docker secrets
Use {source: file} for K8s / Docker secrets
A mounted secret file survives a container restart; a process env var may not. Cross-link: Secret References. File-sourced credentials keep resolving after a restart, so a channel recovers on the next config load without manual intervention.
Alert on the degraded WARNING log line
Alert on the degraded WARNING log line
The
channel will be skipped (degraded) WARNING is your operator canary. Wire it into your alerting so a rotated-but-not-yet-refilled credential pages you before users notice the channel is quiet.Never rely on preflight alone for continuous safety
Never rely on preflight alone for continuous safety
Preflight only checks credentials at start. A token can go stale after preflight passes — expiry, rotation, a secret-store blip. Degraded-channel isolation is what keeps the other channels serving when that happens.
Related
Gateway Secret References
Load credentials from files, env vars, or secret managers.
Gateway CLI
gateway doctor and channels --probe credential availability.Gateway Channel Supervision
CREDENTIAL_UNAVAILABLE state and the refresh_credentials() hook.Gateway Reliability Presets
Drain, admission, and fail-closed opt-outs.

