# WeChat MP API Error Codes (we-mp-rss context)

## Code handling in `core/wx/model/web.py`

```python
# Line 64-69: Two different errors, both break the fetch loop
if msg['base_resp']['ret'] == 200013:   # freq control
    super().Error("frequencey control, stop at {}".format(str(begin)))
    break                                # ← breaks loop, sync_time STILL updates

if msg['base_resp']['ret'] == 200003:   # Invalid Session
    super().Error("Invalid Session, stop at {}".format(str(begin)),code="Invalid Session")
    break                                # ← breaks loop, sync_time STILL updates
```

**Critical**: Both errors cause `Item_Over()` in the `finally` block to run, which updates `feeds.sync_time` — creating a **false positive** where feeds appear "recently synced" but zero articles were fetched.

## Error Codes

| ret | err_msg | Meaning | Action |
|-----|---------|---------|--------|
| 200013 | freq control | WeChat rate-limiting the server IP. Most common on datacenter IPs (腾讯云/阿里云). The session token is valid. | Configure proxy (singbox, Deno Deploy proxy, etc.) |
| 200003 | Invalid Session | WeChat session token expired. Cookies/token in Redis are stale. | User must re-scan QR code at rss.gdcjgk.net |
| 200002 | invalid args | API parameters rejected. Often from `get_acct_list` after QR scan. | Token is still valid — this is a callback-chain issue, not a fetch issue |
| 0 | ok | Success. Response contains `app_msg_list` or `publish_page`. | Normal |

## Diagnostic Flow for "No New Articles"

```
journalctl -u we-mp-rss --no-pager --since "7 days ago" | grep -iE "freq|frequency|Invalid Session|200013"
```

1. **See `frequency control`?** → IP rate limiting. Session is valid. Need proxy.
2. **See `Invalid Session`?** → Session expired. User must re-scan.
3. **See neither?** → Genuine content drought (summer break). Verify manually.

**Never skip step 1.** The user knows their feeds — if they say "they're definitely publishing", trust them and investigate 200013/200003 before concluding drought.

## Real-World Case (2026-08-04)

- July 18: Last successful fetch
- July 19-22: `Invalid Session` (200003) — session genuinely expired
- User rescanned QR code → login_status back to 1, token valid
- July 23-Aug 4: `frequency control, stop at 0` (200013) — **IP rate limited, NOT content drought**
- `sync_time` showed "today 15:30" for both feeds, creating illusion everything was working
- Root cause: Tencent Cloud Lighthouse IP (120.53.228.229) blocked by WeChat anti-bot
- Fix needed: Route WeChat API requests through non-datacenter proxy

## Cooldown Test Result (2026-08-05): INEFFECTIVE for Permanent Blocks

After a 15-hour cooldown (cron paused, SPAN_INTERVAL=30, no requests to WeChat), the first test fetch still returned `frequency control, stop at 0`. This confirms: **cooldown does NOT reset permanent IP blocks**. If the IP is permanently flagged by WeChat (typical for datacenter ranges), cooldown is a waste of time — go straight to proxy (Deno Deploy or singbox).

## Mitigation: Cooldown Approach (try before proxy)

For 200013 (freq control), WeChat's rate limiting is sometimes **temporary** — a burst of requests triggers a cooldown window. Before deploying a full proxy, try:

1. **Pause the fetch cron**: `cronjob action=pause job_id=94d230f73e7f`
2. **Reduce the interval** when resuming: `cronjob action=update job_id=94d230f73e7f schedule=360m`
3. **Increase SPAN_INTERVAL** in systemd to 30s to reduce burst within a fetch cycle
4. **Wait 12+ hours** with zero requests to WeChat
5. **Resume the cron**: `cronjob action=resume job_id=94d230f73e7f`
6. **Test**: manually trigger a fetch or watch the next cron run for `freq control` in logs

If 200013 persists after cooldown → permanent IP block, must use proxy (Deno Deploy or singbox).

## Key Insight: sync_time Is a Liar

`feeds.sync_time` is set in `Item_Over()` which runs in the `finally` block — **always**, regardless of fetch success or failure. A feed showing `sync_time = today` with zero new articles is the hallmark of 200013/200003, not summer break.
