BigPizzaV3/CodexPlusPlus · error · anyhow::Error

微信回复缺少 context_token

Error message

微信回复缺少 context_token

What it means

send_text_chunks refuses to send when context_token is empty or whitespace: WeChat replies must be authorized by the context token that arrived with the inbound message, and a send without one would be rejected upstream. This is a caller-side contract check, not a server error.

Source

Thrown at crates/codex-plus-core/src/connect/weixin.rs:256

        if updates.ret != 0 || updates.errcode != 0 {
            bail!(
                "微信长轮询被拒绝:ret={} errcode={} {}",
                updates.ret,
                updates.errcode,
                updates.errmsg
            );
        }
        Ok(updates)
    }

    pub async fn send_text_chunks(
        &self,
        to_user_id: &str,
        text: &str,
        context_token: &str,
    ) -> anyhow::Result<()> {
        if context_token.trim().is_empty() {
            bail!("微信回复缺少 context_token");
        }
        for chunk in chunk_text(text, MAX_REPLY_CHARS) {
            self.send_text(to_user_id, &chunk, context_token).await?;
            tokio::time::sleep(Duration::from_millis(100)).await;
        }
        Ok(())
    }

    async fn send_text(
        &self,
        to_user_id: &str,
        text: &str,
        context_token: &str,
    ) -> anyhow::Result<()> {
        let request_body = json!({
            "msg": {
                "from_user_id": "",
                "to_user_id": to_user_id,

View on GitHub (pinned to f2074595a2)

Solutions

  1. Thread the inbound message context_token through to every reply
  2. Guard upstream the way run_weixin_connect does: skip or ack messages whose context_token is empty
  3. Populate context_token in test fixtures

Example fix

// before
client.send_text_chunks(&user, &reply, token).await?;
// after: guard the token like the connector loop guards inbound messages
let token = token.trim();
if token.is_empty() { return Ok(()); }
client.send_text_chunks(&user, &reply, token).await?;
Defensive patterns

Strategy: validation

Validate before calling

let token = message.context_token.trim();
if token.is_empty() {
    // mirror the connector loop: skip or ack instead of attempting a send
    return Ok(());
}
client.send_text_chunks(&message.from_user_id, &reply, token).await?;

Prevention

When it happens

Trigger: Calling send_text_chunks with a blank token, for example constructing WeixinMessage manually or a reply path where message.context_token was never populated. The built-in loop skips inbound messages lacking a token before processing, so hitting this usually means custom code.

Common situations: Custom integrations replying outside the standard loop; refactors that drop the token field; test fixtures with messages missing context_token.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@f2074595a2 (2026-08-23). Data as JSON: /api/errors/aa6f305a377acd26. Report an issue: GitHub.