larksuite/cli · error
fetch bot info: open_id is empty
Error message
fetch bot info: open_id is empty
What it means
The bot info response succeeded (code 0) but the bot object has an empty open_id, so no usable bot identity exists. The library treats bot identity as mandatory output of this endpoint; an empty open_id implies a malformed or semantically empty bot record.
Source
Thrown at shortcuts/common/runner.go:190
}
// /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 {
return ctx.apiClientFunc()
}
return ctx.Factory.NewAPIClientWithConfig(ctx.Config)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Enable the bot capability for the app and confirm a bot instance exists in the tenant, then retry
- If the endpoint legitimately returns no bot, stop relying on bot identity: pass the identity explicitly or use user-based identity flows
- File/report a schema issue if the API returns code 0 with an empty bot object unexpectedly
Example fix
// before
info, _ := ctx.BotInfo()
useId(info.OpenID) // "open_id is empty" upstream
// after
info, err := ctx.BotInfo()
if err != nil || info.OpenID == "" { return errs.NewValidationError(errs.SubtypeFailedPrecondition, "bot identity unavailable; pass --attendee explicitly") } Defensive patterns
Strategy: validation
Validate before calling
info, err := ctx.BotInfo()
if err == nil && info.OpenID == "" {
// treat as unavailable identity; require explicit ID
} Type guard
func hasBotIdentity(info *common.BotInfo) bool { return info != nil && info.OpenID != "" } Try / catch
info, err := ctx.BotInfo()
if err != nil || info == nil || info.OpenID == "" {
return errs.NewValidationError(errs.SubtypeFailedPrecondition, "bot identity unavailable; provide the attendee/identity explicitly")
} Prevention
- Ensure the app has the bot capability enabled so /bot/v3/info returns a real bot record
- Always nil/empty-check BotInfo.OpenID before using it as an ID
- Offer an explicit identity flag as a fallback in commands that need an ID
When it happens
Trigger: envelope.Data.OpenID == "" after successful decode — e.g. app has no bot bound, the tenant stripped identity fields, or the endpoint returned an empty bot object.
Common situations: App created without adding the bot capability, so /bot/v3/info returns an empty bot; region/tenant configurations that omit open_id.
Related errors
- v0.2 index contains no skills
- 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
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/24d8f8e6f4398e18.
Report an issue: GitHub.