Skip to main content

Troubleshooting: WeChat and Zalo CHANNEL_NOT_CONFIGURED and credential precedence

WeChat and Zalo are bring-your-own-credential beta channels. A send on either fails closed503 CHANNEL_NOT_CONFIGURED — when neither your organization’s credential row nor the operator’s platform default is set; and it fails silently as the wrong account when both are set and precedence was not what you expected. This page covers the resolution order, the expiry drift on WeChat’s ~2-hour token, and the inbound-reply gap that shows up after a credential rotation. The content-side gates (VALIDATION_ERROR on templates) are covered by Troubleshooting: KakaoTalk Alimtalk and Friendtalk gates, and the inbound-routing matrix is covered by Troubleshooting: APAC inbound no-route.

Resolution order — per-organization wins

Both channels resolve credentials the same way, mirrored on the WeChat channel page and Zalo channel page:
  1. Per-organization credentials connected under Settings → Channels → WeChat (or Zalo) — stored encrypted at rest.
  2. Platform default — a cluster-wide credential the operator sets with an environment variable (DEVOTEL_WECHAT_ACCESS_TOKEN or DEVOTEL_ZALO_ACCESS_TOKEN), consulted only when the organization has none.
If neither is set, the provider never registers and every send fails closed with 503 CHANNEL_NOT_CONFIGURED. If both are set, every send goes as the per-organization brand — the platform default is invisible to that organization until the row is removed.

Symptom map

Why CHANNEL_NOT_CONFIGURED is fail-closed by design

The point of the check is to stop a missing credential from sending anyway on the platform default, which would put a customer’s brand under an unexpected Official Account. The same check that produces the 503 is the thing that prevents wrong-brand sends. When you see it, treat it as “the channel is safely refusing the send,” not as a broken integration.

Worked example — a WeChat send that succeeded on the wrong account

Support says: “our WeChat sends land on a random OA we do not recognize.” The check sequence:
  1. Open Settings → Channels → WeChat. Note whether a row exists.
  2. If a row does exist, its OA is the one sending — that is precedence, not leakage. Replace the token with the one you intend.
  3. If no row exists, the platform default is the sender — either accept that and proceed, or ask your operator which cluster default is set.
The channel page for WeChat’s own pre-send checks lives at WeChat channel page; the Zalo equivalent is at Zalo channel page.

Worked example — a WeChat token that expires on a leash

WeChat’s cgi-bin/token grant returns a token good for about two hours. A rotation sidecar that re-pastes every 1h50m from your own refresh loop keeps the channel working; a manual paste schedule keeps it broken half the time.
Treat inbound on the same WeChat channel separately: replies are addressed to your OA’s open id / follower id relation, which survives token rotation but not a switch to a different OA. The inbound side of the channel page (TEMPLATESENDJOBFINISH callbacks, reply normalization) is at WeChat channel page — Receive inbound replies.

What not to try

  • Do not set the platform default to mask a missing per-org row. A wrong-brand send to your customers is far worse than the 503 the channel was trying to save you from. Connect the per-organization row instead.
  • Do not retry a 503. Validation and configuration errors are deterministic — the same request fails every time.
  • Do not rotate a WeChat token by hand under a cadence you will not sustain at ~2-hour intervals. Either run a refresh job or, on higher tiers, use WeChat’s stable-token grant type if you are provisioned for it.
  • Do not edit the credential row by hand inside tenant data — the dashboard writes it under settings.channels.wechat / settings.channels.zalo encrypted at rest; direct tenant edits break the decrypt envelope. Connect/disconnect through the dashboard surface.

When to escalate

Open a support ticket when the connected row exists (verified in the dashboard) and sends still return 503, or when the resolution chain itself precedes a value that contradicts what the dashboard shows. Include:
  • Your tenant id (dashboard under Settings → Organization, or organizationId on GET /api/v1/me).
  • Whether a platform default was set on your cluster and when.
  • One request ID of a failing send.
  • The channel — wechat or zalo — plus whether you are using the direct endpoint or the campaign route.

See also