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

  1. Cross-reference the embedded code with Feishu's error-code table.
  2. Validate that msgType/content JSON is well-formed (use json.Marshal for the content payload).
  3. Confirm the bot is still a member of the target chat and holds im:message scopes.
  4. 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

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.