chenhg5/cc-connect · error
%s: %s failed code=%d msg=%s
Error message
%s: %s failed code=%d msg=%s
What it means
The Feishu Create-message API returned a business error: the response indicates !resp.Success() and the Feishu code/msg are embedded in the message. Feishu explicitly rejected sending the message (bad receive_id, permission, invalid msg_type/content, or rate limit).
Source
Thrown at platform/feishu/feishu.go:4081
}
func (p *Platform) createMessage(ctx context.Context, chatID, msgType, content, op string) error {
req := larkim.NewCreateMessageReqBuilder().
ReceiveIdType(larkim.ReceiveIdTypeChatId).
Body(larkim.NewCreateMessageReqBodyBuilder().
ReceiveId(chatID).
MsgType(msgType).
Content(content).
Build()).
Build()
return p.withTransientRetry(ctx, op, func() error {
return p.withFreshTenantAccessTokenRetry(ctx, op, func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {
resp, err := client.Im.Message.Create(ctx, req, options...)
if err != nil {
return fmt.Errorf("%s: %s api call: %w", p.tag(), op, err)
}
if !resp.Success() {
return fmt.Errorf("%s: %s failed code=%d msg=%s", p.tag(), op, resp.Code, resp.Msg)
}
return nil
})
})
}
func (p *Platform) withFreshTenantAccessTokenRetry(ctx context.Context, operation string, fn feishuRequestFunc) error {
err := fn(p.client)
if !isTenantAccessTokenInvalid(err) {
return err
}
freshToken, refreshErr := p.fetchFreshTenantAccessToken(ctx)
if refreshErr != nil {
return fmt.Errorf("%s: %s failed after token refresh attempt: %w (original error: %v)", p.tag(), operation, refreshErr, err)
}
slog.Warn(p.tag()+": retrying request with fresh tenant access token", "operation", operation)View on GitHub (pinned to 4000b2338a)
Solutions
- Cross-reference the embedded code with Feishu's error-code table.
- Validate that msgType/content JSON is well-formed (use json.Marshal for the content payload).
- Confirm the bot is still a member of the target chat and holds im:message scopes.
- Apply backoff if the code indicates rate limiting.
Example fix
// before
content := fmt.Sprintf("{\"text\":\"%s\"}", text)
// after
contentBytes, _ := json.Marshal(map[string]string{"text": text})
content := string(contentBytes) Defensive patterns
Strategy: validation
Validate before calling
contentBytes, err := json.Marshal(map[string]string{"text": text})
if err != nil { return err }
if chatID == "" { return errors.New("missing chat_id") } Try / catch
err := p.sendMessage(ctx, chatID, msgType, content)
if err != nil {
var code int
if extractFeishuCode(err, &code) && code == 99991400 {
time.Sleep(backoff)
return p.sendMessage(ctx, chatID, msgType, content)
}
return err
} Prevention
- Always build content via json.Marshal, never string concatenation.
- Use core message-type constants instead of raw strings.
- Throttle outbound sends to stay under Feishu QPS limits.
- Verify bot chat membership after membership-change webhooks.
When it happens
Trigger: client.Im.Message.Create succeeds at HTTP level but body code != 0 — invalid chat_id, bot not in the chat, malformed JSON content for the msg_type, missing im:message scope, or QPS limit exceeded.
Common situations: Sending to a chat the bot was removed from, passing non-JSON-escaped text as content, wrong msgType string (e.g. 'text' vs 'interactive'), or burst traffic triggering rate limiting.
Related errors
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/4a8f0336d3d0359e.
Report an issue: GitHub.