> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting: WeChat and Zalo CHANNEL_NOT_CONFIGURED and credential precedence

> Work through why a WeChat or Zalo send fails with 503 CHANNEL_NOT_CONFIGURED, and why a send succeeds but lands as the wrong brand — per-organization vs platform-default credential resolution, short-lived token expiry, and rotated incoming credentials that stranded inbound.

# 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 **closed** — `503 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](/troubleshooting/kakao-template-gates),
and the inbound-routing matrix is covered by
[Troubleshooting: APAC inbound no-route](/troubleshooting/apac-channel-inbound-no-route).

## Resolution order — per-organization wins

Both channels resolve credentials the same way, mirrored on the
[WeChat channel page](/channels/wechat#platform-default) and
[Zalo channel page](/channels/zalo#platform-default):

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

| Symptom                                                                                     | Most likely cause                                                                                    | What to do                                                                                                                                                          |
| ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **First send returns 503 `CHANNEL_NOT_CONFIGURED`**                                         | No per-org row, and the operator set no platform default                                             | Connect under **Settings → Channels → WeChat** (access token) or **→ Zalo** (ZNS access token) — the checkbox row enables the provider at once                      |
| **Send succeeds, but as the wrong Official Account / Zalo OA**                              | Both layers are set; the per-org row won                                                             | This is precedence, not a bug — remove the per-org row if you intend the platform default, or replace it with the credential you mean to use                        |
| **503 after a long-lived period of working sends**                                          | Per-org row deleted or the operator rotated the platform default out from under the tenant           | Check **Settings → Channels** first; if the row is still there, ask your operator for the platform-default rotation status                                          |
| **503 that recurs exactly at fixed intervals (typically \~2 hours) on WeChat but not Zalo** | The WeChat OA `cgi-bin/token` access token lapses (\~2 h lifetime) and was never refreshed centrally | Rotate the token through your own refresh job, re-paste under **Settings → Channels → WeChat**; better — let a credential-rotation sidecar re-paste ahead of expiry |
| **Inbound replies stop after you rotated the credential**                                   | The sender profile the replies address changed — inbound is keyed on the connected OA, not the token | Re-connect and re-subscribe inbound — the *previous* OA's replies keep landing as nobody's inbound                                                                  |

## 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](/channels/wechat); the Zalo equivalent is at
[Zalo channel page](/channels/zalo).

## 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.

```bash theme={null}
# After your own refresh job mints a new token, re-paste it under
# Settings → Channels → WeChat — the row is overwritten in place.
```

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](/channels/wechat#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

* [WeChat channel page](/channels/wechat) — the channel's full error table,
  token grant details, and inbound-reply wiring
* [Zalo channel page](/channels/zalo) — the ZNS credential and template flow
* [KakaoTalk template gates](/troubleshooting/kakao-template-gates) — the
  `VALIDATION_ERROR` layer that sits above credentials
* [APAC inbound no-route](/troubleshooting/apac-channel-inbound-no-route) —
  the inbound-reply matrix when replies stop after rotation
