larksuite/cli · error

L3: inputSchema `yes` property=%v inconsistent with risk=%q

Error message

L3: inputSchema `yes` property=%v inconsistent with risk=%q

What it means

Envelope-level (L3) lint rule in internal/schema/lint.go's lintEnvelope. The inputSchema must contain a boolean `yes` property if and only if the envelope is a high-risk write (Meta.Risk == core.RiskHighRiskWrite). It enforces that dangerous operations expose an explicit confirmation field, and it fires when that correspondence is broken in either direction.

Source

Thrown at internal/schema/lint.go:97

			}
		}
	}

	// ---- L3: cross-field self-consistency ----
	dangerExpected := env.Meta.Risk == core.RiskWrite || env.Meta.Risk == core.RiskHighRiskWrite
	if env.Meta.Danger != dangerExpected {
		errs = append(errs, fmt.Errorf("L3: _meta.danger=%v inconsistent with risk=%q", env.Meta.Danger, env.Meta.Risk))
	}

	// `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.

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Add a boolean `yes` property to InputSchema.Properties for high-risk writes
  2. Remove the `yes` property if the operation is not a high-risk write
  3. Set Meta.Risk to RiskHighRiskWrite if the operation really needs confirmation
  4. Run the lint (TestAllEnvelopesPass) to see the reported property/risk mismatch

Example fix

// before
Meta: {Risk: core.RiskHighRiskWrite}, InputSchema: {Properties: {Map: {"task_id": ...}}}
// after
InputSchema: {Properties: {Map: {"task_id": ..., "yes": {Type: "boolean", Description: "confirm high-risk write"}}}}
Defensive patterns

Strategy: validation

Validate before calling

for _, env := range envelopes {
  _, hasYes := env.InputSchema.Properties.Map["yes"]
  if hasYes != (env.Meta.Risk == core.RiskHighRiskWrite) {
    t.Errorf("envelope %s: `yes` property / risk mismatch", env.Name)
  }
}

Type guard

func needsYesConfirmation(risk core.Risk) bool { return risk == core.RiskHighRiskWrite }

Prevention

When it happens

Trigger: Registering an envelope whose Meta.Risk is RiskHighRiskWrite but whose InputSchema.Properties has no `yes` key, or declaring a `yes` property on an envelope whose risk is not high-risk-write.

Common situations: Promoting a shortcut to high-risk and forgetting to add the `yes` confirmation field; copying a high-risk envelope as a template for a low-risk command and leaving `yes` behind; editing the risk constant in meta without re-linting.

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/10ea564d2b15a213. Report an issue: GitHub.