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

  1. Replace the invalid value with "user", "bot", or both
  2. Fix casing to exact lowercase "user"/"bot"
  3. 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

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


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