larksuite/cli · error

fetch bot info: HTTP %d

Error message

fetch bot info: HTTP %d

What it means

The bot info endpoint returned an HTTP status >= 400, so the response is not usable. The library reports the status code without parsing a body, because at this layer the status alone indicates the API rejected the request (auth, permissions, or gateway error).

Source

Thrown at shortcuts/common/runner.go:171

		return nil, fmt.Errorf("BotInfo not available (runtime context not fully initialized)")
	}
	return ctx.botInfoFunc()
}

// fetchBotInfo calls /bot/v3/info using bot identity and parses the response.
func (ctx *RuntimeContext) fetchBotInfo() (*BotInfo, error) {
	if !ctx.Config.CanBot() {
		return nil, fmt.Errorf("fetch bot info: bot identity is not available in current credential context")
	}
	resp, err := ctx.DoAPIAsBot(&larkcore.ApiReq{
		HttpMethod: http.MethodGet,
		ApiPath:    "/open-apis/bot/v3/info",
	})
	if err != nil {
		return nil, fmt.Errorf("fetch bot info: %w", err)
	}
	if resp.StatusCode >= 400 {
		return nil, fmt.Errorf("fetch bot info: HTTP %d", resp.StatusCode)
	}
	// /open-apis/bot/v3/info returns `{code, msg, bot: {...}}` — the bot
	// payload is under "bot", not "data" as the newer Lark API convention.
	var envelope struct {
		Code int    `json:"code"`
		Msg  string `json:"msg"`
		Data struct {
			OpenID  string `json:"open_id"`
			AppName string `json:"app_name"`
		} `json:"bot"`
	}
	if err := json.Unmarshal(resp.RawBody, &envelope); err != nil {
		return nil, fmt.Errorf("fetch bot info: unmarshal: %w", err)
	}
	if envelope.Code != 0 {
		return nil, fmt.Errorf("fetch bot info: [%d] %s", envelope.Code, envelope.Msg)
	}
	if envelope.Data.OpenID == "" {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Check the HTTP status in the message: 401/403 → fix bot credentials/scopes; 404 → verify API base URL; 5xx → retry later
  2. Grant the app the scopes required for /open-apis/bot/v3/info and enable bot capability
  3. Re-run after refreshing credentials; if persistent, capture the raw response with debug logging to see the error body
Defensive patterns

Strategy: try-catch

Try / catch

info, err := ctx.BotInfo()
if err != nil {
	var httpErr struct{ Status int }
	if m := regexp.MustCompile(`HTTP (\d+)`).FindStringSubmatch(err.Error()); m != nil {
		switch m[1] {
		case "401", "403": /* fix scopes/credentials */
		case "404": /* check base URL */
		default: /* retry later for 5xx */
		}
	}
	return err
}

Prevention

When it happens

Trigger: DoAPIAsBot succeeded at transport level but /bot/v3/info replied 4xx/5xx — e.g. 401/403 from missing bot scopes or invalid bot token, 404 from wrong API base/gateway, 5xx from server-side issues.

Common situations: App missing the bot capability or required scopes for /bot/v3/info; stale token after credential rotation; misconfigured gateway/base-URL override pointing at the wrong environment.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/1c9fe9920a5556e0. Report an issue: GitHub.