Tencent/WeKnora · error

corp_id mismatch: expected %s, got %s

Error message

corp_id mismatch: expected %s, got %s

What it means

The WeCom plaintext ends with the corp_id (corporation's CorpID) of the intended recipient; decrypt() compares it against the adapter's configured corpID and rejects mismatches. This prevents cross-tenant message confusion — a callback intended for one app/corp being processed by another. The error message includes both expected and received values for diagnosis.

Source

Thrown at internal/im/wecom/webhook_adapter.go:497

	}
	plaintext := ciphertext[:len(ciphertext)-padLen]

	// WeCom format: random(16) + msg_len(4) + msg + corp_id
	if len(plaintext) < 20 {
		return nil, fmt.Errorf("plaintext too short")
	}

	msgLen := binary.BigEndian.Uint32(plaintext[16:20])
	if uint32(len(plaintext)) < 20+msgLen {
		return nil, fmt.Errorf("message length mismatch")
	}

	msgBytes := plaintext[20 : 20+msgLen]

	// Verify corp_id from plaintext tail
	corpIDBytes := plaintext[20+msgLen:]
	if string(corpIDBytes) != a.corpID {
		return nil, fmt.Errorf("corp_id mismatch: expected %s, got %s", a.corpID, string(corpIDBytes))
	}

	return msgBytes, nil
}

// callbackRequestBody is the XML structure of a WeCom callback request body.
type callbackRequestBody struct {
	XMLName    xml.Name `xml:"xml"`
	ToUserName string   `xml:"ToUserName"`
	Encrypt    string   `xml:"Encrypt"`
	AgentID    string   `xml:"AgentID"`
}

// wecomMessage is the decrypted WeCom message structure.
// Supports text, image, voice, video, location, and link message types.
// Reference: https://developer.work.weixin.qq.com/document/path/90375
type wecomMessage struct {
	XMLName      xml.Name `xml:"xml"`

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Compare the 'got' value in the error with your WeCom admin CorpID — fix the config if expected is wrong
  2. If multi-corp: route callbacks to adapters by the ToUserName field in the callback XML before decrypting
  3. Confirm the Token/EncodingAESKey/corpID triple all belong to the same WeCom self-built app
  4. Update deployment env vars for the corp whose credentials changed

Example fix

// before: one global corp id
adapter := wecom.NewWebhookAdapter(token, aesKey, "corp_old")
// after: per-corp routing
adapter, ok := adapters[callback.ToUserName]
if !ok { http.Error(w, "unknown corp", 404); return }
Defensive patterns

Strategy: validation

Validate before calling

// verify corp identity after decrypt, before processing
// (library already enforces this; ensure config corpID is correct at startup)
if corpID == "" || corpID != expectedCorpID { return errors.New("misconfigured corpID") }

Try / catch

msg, err := adapter.ParseCallback(sig, ts, nonce, enc)
if err != nil && strings.Contains(err.Error(), "corp_id mismatch") {
    logger.Errorf("callback for wrong corp: %v", err)
    http.Error(w, "wrong tenant", http.StatusForbidden)
    return
}

Prevention

When it happens

Trigger: Callback from corp A delivered to an adapter configured with corp B's credentials; multi-corp deployments sharing one webhook URL; configured corp_id typo or stale value after the company changed its WeCom account.

Common situations: One endpoint serving multiple WeCom corps without routing by the XML ToUserName; copying another environment's corp ID into config; tenant onboarding with wrong credentials.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/cfb1fe38b24d9a3d. Report an issue: GitHub.