larksuite/cli · error
L3: _meta.access_tokens contains invalid value %q (allowed:
Error message
L3: _meta.access_tokens contains invalid value %q (allowed: user, bot)
What it means
L3 lint rule requiring every envelope's Meta.AccessTokens to contain only `user` and/or `bot`. Access tokens describe which Lark identities the method may be called with; an unrecognized value would produce an invalid _meta.access_tokens in the published schema.
Source
Thrown at internal/schema/lint.go:105
}
// `yes` lives at inputSchema.properties.yes (sibling of params/data),
// injected only for risk == RiskHighRiskWrite.
hasYes := false
if env.InputSchema != nil && env.InputSchema.Properties != nil {
_, hasYes = env.InputSchema.Properties.Map["yes"]
}
wantYes := env.Meta.Risk == core.RiskHighRiskWrite
if hasYes != wantYes {
errs = append(errs, fmt.Errorf("L3: inputSchema `yes` property=%v inconsistent with risk=%q", hasYes, env.Meta.Risk))
}
if len(env.Meta.AccessTokens) == 0 {
errs = append(errs, errors.New("L3: _meta.access_tokens must not be empty"))
}
for _, t := range env.Meta.AccessTokens {
if !validAccessTokens[t] {
errs = append(errs, fmt.Errorf("L3: _meta.access_tokens contains invalid value %q (allowed: user, bot)", t))
}
}
return errs
}
// walkForL2 recursively applies per-field L2 checks (format:binary on
// non-string; minimum>=maximum) plus the sub-object required-exists invariant.
// Required only matters on object-typed Properties (e.g. the params / data
// wrappers); leaf scalars ignore it.
func walkForL2(props *OrderedProps, errs *[]error) {
if props == nil {
return
}
for _, k := range props.Order {
p := props.Map[k]
if p.Format == "binary" && p.Type != "string" {
*errs = append(*errs, fmt.Errorf("L2: field %q has format: binary but type = %q (want string)", k, p.Type))View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Replace the invalid value with "user", "bot", or both
- Fix casing to exact lowercase "user"/"bot"
- Check validAccessTokens in internal/schema for the allowed set
Example fix
// before
Meta: {AccessTokens: []string{"User"}}
// after
Meta: {AccessTokens: []string{"user", "bot"}} Defensive patterns
Strategy: validation
Validate before calling
var validAccessTokens = map[string]bool{"user": true, "bot": true}
for _, t := range env.Meta.AccessTokens {
if !validAccessTokens[t] {
t.Errorf("envelope %s: invalid access token %q", env.Name, t)
}
}
if len(env.Meta.AccessTokens) == 0 {
t.Errorf("envelope %s: access_tokens empty", env.Name)
} Type guard
func validAccessToken(s string) bool { return s == "user" || s == "bot" } Prevention
- Use only the literal strings "user" and "bot" for access tokens
- Always list at least one access token per envelope
- Define token constants once and reference them instead of raw strings
- Run the schema lint tests after editing envelope metadata
When it happens
Trigger: lintEnvelope is called on an envelope where Meta.AccessTokens is empty (separate L3 error) or contains a token string other than "user" or "bot" (typo, capitalization like "User", or a made-up identity).
Common situations: Typo when hand-writing envelope metadata; copy-pasted token list from another system; renaming an identity without updating all envelopes.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- L3: _meta.danger=%v inconsistent with risk=%q
- L1: _meta must not be nil
- L1: inputSchema.type = %q, want "object"
- L1: outputSchema.type = %q, want "object"
- L1: _meta.envelope_version = %q, want "1.0"
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/920c3cf93dfec139.
Report an issue: GitHub.