zeroclaw-labs/zeroclaw · error · anyhow::Error
gateway registration failed ({status}): {err}
Error message
gateway registration failed ({status}): {err} What it means
DingTalkChannel's register_connection POSTs clientId/clientSecret plus a CALLBACK subscription for /v1.0/im/bot/messages/get to https://api.dingtalk.com/v1.0/gateway/connections/open (Stream Mode). Any non-2xx becomes this error with the status and body. Both listen() startup and health_check() route through it, so credential or endpoint problems surface here first, before any WebSocket is opened.
Source
Thrown at crates/zeroclaw-channels/src/dingtalk.rs:130
"subscriptions": [
{
"type": "CALLBACK",
"topic": DINGTALK_BOT_CALLBACK_TOPIC,
}
],
});
let resp = self
.http_client()
.post("https://api.dingtalk.com/v1.0/gateway/connections/open")
.json(&body)
.send()
.await?;
if !resp.status().is_success() {
let status = resp.status();
let err = resp.text().await.unwrap_or_default();
anyhow::bail!("gateway registration failed ({status}): {err}");
}
let gw: GatewayResponse = resp.json().await?;
Ok(gw)
}
}
impl ::zeroclaw_api::attribution::Attributable for DingTalkChannel {
fn role(&self) -> ::zeroclaw_api::attribution::Role {
::zeroclaw_api::attribution::Role::Channel(
::zeroclaw_api::attribution::ChannelKind::DingTalk,
)
}
fn alias(&self) -> &str {
&self.alias
}
}
View on GitHub (pinned to 88bb9c8533)
Solutions
- Decode the status/body in the message — DingTalk returns a specific errorCode/message (e.g. invalid clientSecret)
- Re-copy Client ID and Client Secret from the DingTalk Open Platform app into [channels.dingtalk.<alias>]
- Confirm the app has the bot/message-receive capability and Stream Mode enabled
- For EU apps the endpoint must be api.dingtalk.eu — currently hardcoded, so use an international app or patch the URL
- Remove or verify proxy_url if a proxy intercepts the registration POST
Defensive patterns
Strategy: validation
Validate before calling
// register_connection is what health_check exercises:
if !dingtalk_channel.health_check().await {
// gateway registration failed — fix client_id/client_secret/region before listen()
} Try / catch
if let Err(e) = channel.listen(tx).await {
if e.to_string().contains("gateway registration failed") {
// credential/endpoint problem: reconnect loops will keep failing until config is fixed
}
} Prevention
- Call health_check at startup and skip reconnect loops while it fails
- Rotate the DingTalk secret in config the moment you rotate it in the console
- Pin the app region and the API host together — EU apps need api.dingtalk.eu
When it happens
Trigger: Invalid or rotated clientSecret; clientId of an app whose bot capability is not enabled; region mismatch — the code hardcodes api.dingtalk.com while EU apps must use api.dingtalk.eu; server IP not on the app allowlist; app not published/approved so Stream Mode is refused; per-channel proxy (build_channel_proxy_client) mangling the POST.
Common situations: Secret regenerated in the DingTalk developer console while config still holds the old one; EU-hosted app against the international host; corporate proxy blocking api.dingtalk.com; sandbox apps without stream permission.
Related errors
- WeCom WebSocket stream_mode={} is not supported; use partial
- WebSocket stream ended
- matrix: {reason} Cannot auto-recover because channels.matrix
- matrix login requires either access_token or user_id+passwor
- matrix: configured channels.matrix.user-id ({configured}) do
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/223da063d118cafc.
Report an issue: GitHub.