Tencent/WeKnora · error

wechat credentials require bot_token and ilink_bot_id

Error message

wechat credentials require bot_token and ilink_bot_id

What it means

After successfully parsing the WeChat channel's credentials JSON, the factory requires both the bot_token and ilink_bot_id keys to be present and non-empty. This error is returned when either key is missing or an empty string, indicating an incomplete credential configuration for the iLink bot.

Source

Thrown at internal/im/wechat/factory.go:24

	"github.com/Tencent/WeKnora/internal/im"
	"github.com/Tencent/WeKnora/internal/logger"
)

// NewFactory returns an im.AdapterFactory for WeChat channels (iLink bot).
// WeChat only supports a long-polling mode, so there is no mode branch.
func NewFactory() im.AdapterFactory {
	return func(factoryCtx context.Context, channel *im.IMChannel, msgHandler func(context.Context, *im.IncomingMessage) error) (im.Adapter, context.CancelFunc, error) {
		creds, err := im.ParseCredentials(channel.Credentials)
		if err != nil {
			return nil, nil, fmt.Errorf("parse wechat credentials: %w", err)
		}

		botToken := im.GetString(creds, "bot_token")
		ilinkBotID := im.GetString(creds, "ilink_bot_id")

		if botToken == "" || ilinkBotID == "" {
			return nil, nil, fmt.Errorf("wechat credentials require bot_token and ilink_bot_id")
		}

		adapter := NewAdapter(botToken, ilinkBotID)
		client := NewLongPollClient(botToken, ilinkBotID, msgHandler)

		pollCtx, pollCancel := context.WithCancel(context.Background())
		go func() {
			if err := client.Start(pollCtx); err != nil && pollCtx.Err() == nil {
				logger.Errorf(context.Background(), "[IM] WeChat long-poll stopped for channel %s: %v", channel.ID, err)
			}
		}()

		return adapter, pollCancel, nil
	}
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Add both keys to the channel credentials JSON: {"bot_token":"<token>","ilink_bot_id":"<id>"}.
  2. Fetch the missing ilink_bot_id from the WeChat iLink bot settings and store it on the channel.
  3. Add a pre-save validation on IMChannel for WeChat channels checking both keys are non-empty.

Example fix

// before
ch.Credentials = `{"bot_token":"abc"}`
// after
ch.Credentials = `{"bot_token":"abc","ilink_bot_id":"ilink-123"}`
Defensive patterns

Strategy: validation

Validate before calling

creds, err := im.ParseCredentials(ch.Credentials)
if err == nil {
    if im.GetString(creds, "bot_token") == "" || im.GetString(creds, "ilink_bot_id") == "" {
        return fmt.Errorf("wechat channel %d: credentials must include non-empty bot_token and ilink_bot_id", ch.ID)
    }
}

Type guard

func weChatCredsComplete(raw string) bool {
    creds, err := im.ParseCredentials(raw)
    if err != nil {
        return false
    }
    return im.GetString(creds, "bot_token") != "" && im.GetString(creds, "ilink_bot_id") != ""
}

Try / catch

adapter, cancel, err := wechatFactory(ctx, ch, handler)
if err != nil {
    if strings.Contains(err.Error(), "bot_token and ilink_bot_id") {
        return fmt.Errorf("channel %d missing iLink credentials — set bot_token and ilink_bot_id", ch.ID)
    }
    return err
}

Prevention

When it happens

Trigger: Invoking the WeChat factory with a channel whose credentials JSON parses but lacks bot_token and/or ilink_bot_id, or has them set to "".

Common situations: Only the bot token was provisioned and the iLink bot ID was never copied from the WeChat admin console; placeholder values left empty in a config template; redacted credentials injected by a CI secret system that dropped one key.

Related errors


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