larksuite/cli · error
fetch bot info: [%d] %s
Error message
fetch bot info: [%d] %s
What it means
The /bot/v3/info envelope decoded fine but carries a non-zero business code, meaning the Lark API itself rejected the logical request. The message surfaces the API's own code and msg so the developer can map it to Lark's error taxonomy (e.g. permission denied, invalid token).
Source
Thrown at shortcuts/common/runner.go:187
}
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 == "" {
return nil, fmt.Errorf("fetch bot info: open_id is empty")
}
return &BotInfo{OpenID: envelope.Data.OpenID, AppName: envelope.Data.AppName}, nil
}
// Ctx returns the context.Context propagated from cmd.Context().
func (ctx *RuntimeContext) Ctx() context.Context { return ctx.ctx }
// getAPIClient returns the cached APIClient, creating it on first use.
// Thread-safe via sync.OnceValues (initialized in newRuntimeContext).
// Falls back to direct construction for test contexts that bypass newRuntimeContext.
func (ctx *RuntimeContext) getAPIClient() (*client.APIClient, error) {
if ctx.offline {
return nil, errs.NewValidationError(errs.SubtypeFailedPrecondition, "OpenAPI requests are unavailable during dry-run")
}
if ctx.apiClientFunc != nil {View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Look up the returned code in Lark's API error docs and apply the mapped fix (scopes, token, app state)
- Regenerate/refresh the app access token for the bot identity
- Confirm the app is enabled and bot capability is turned on in the developer console
Defensive patterns
Strategy: fallback
Try / catch
info, err := ctx.BotInfo()
if err != nil {
var apiErr *lark.APIError
if errors.As(err, &apiErr) { /* map apiErr.Code via Lark docs */ }
if strings.Contains(err.Error(), "fetch bot info: ["){ /* business code in message: surface to user */ }
return err
} Prevention
- Map non-zero Lark business codes to concrete remediation (scopes, token, app state)
- Keep app access tokens current and tenant-scoped
- Confirm the app is published/enabled in the tenant before bot calls
When it happens
Trigger: envelope.Code != 0 in the bot info response — e.g. invalid app access token, bot capability disabled for the app, or tenant-level restriction on bot info.
Common situations: Token mismatched to tenant/app; app not published/enabled in the tenant; insufficient bot scopes for /bot/v3/info.
Related errors
- BotInfo not available (runtime context not fully initialized
- fetch bot info: bot identity is not available in current cre
- fetch bot info: %w
- fetch bot info: HTTP %d
- fetch bot info: open_id is empty
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/357015b00b34f9cf.
Report an issue: GitHub.