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
- Compare the 'got' value in the error with your WeCom admin CorpID — fix the config if expected is wrong
- If multi-corp: route callbacks to adapters by the ToUserName field in the callback XML before decrypting
- Confirm the Token/EncodingAESKey/corpID triple all belong to the same WeCom self-built app
- 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
- Copy CorpID exactly from the WeCom admin console ('my company' page)
- In multi-tenant setups, instantiate one adapter per corp keyed by CorpID/ToUserName
- Include corpID in deployment config review checklists
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
- sandbox binding requires tenant and session
- ciphertext too short
- no file URL in message
- invite code has expired
- join request not found
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/cfb1fe38b24d9a3d.
Report an issue: GitHub.