larksuite/cli · error

L3: _meta.danger=%v inconsistent with risk=%q

Error message

L3: _meta.danger=%v inconsistent with risk=%q

What it means

lintEnvelope's L3 cross-field consistency check requires _meta.danger to equal (risk == write || risk == high_risk_write). This error is thrown when danger disagrees with the declared risk level — danger true with a non-write risk, or danger false with a write/high-risk-write risk.

Source

Thrown at internal/schema/lint.go:86

	}

	// ---- L2: type-level consistency ----
	if env.InputSchema != nil && env.InputSchema.Properties != nil {
		// Walk the whole property tree so format/min-max checks reach leaf
		// fields nested under the params/data wrapper.
		walkForL2(env.InputSchema.Properties, &errs)
		// Top-level required keys must exist in top-level properties.
		for _, r := range env.InputSchema.Required {
			if _, ok := env.InputSchema.Properties.Map[r]; !ok {
				errs = append(errs, fmt.Errorf("L2: required key %q not found in properties", r))
			}
		}
	}

	// ---- 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] {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Set _meta.danger = true when risk is write or high_risk_write, false otherwise.
  2. If the tool is not really mutating, downgrade risk instead of forcing danger.
  3. Re-run the lint to confirm L3 cross-field consistency and that yes-property presence matches high_risk_write.

Example fix

// before
"_meta": { "risk": "read", "danger": true }
// after
"_meta": { "risk": "read", "danger": false }
Defensive patterns

Strategy: validation

Validate before calling

func dangerMatchesRisk(meta map[string]any) bool {
	risk, _ := meta["risk"].(string)
	danger, _ := meta["danger"].(bool)
	return danger == (risk == "write" || risk == "high_risk_write")
}

Type guard

func dangerConsistent(meta *Meta) bool { return meta.Danger == (meta.Risk == core.RiskWrite || meta.Risk == core.RiskHighRiskWrite) }

Try / catch

errs := lintEnvelope(env)
for _, e := range errs {
	if strings.Contains(e.Error(), "_meta.danger") {
		// align danger with risk: true for write/high_risk_write, else false
	}
}

Prevention

When it happens

Trigger: Linting an envelope where _meta.risk is e.g. "read" but _meta.danger is true, or risk is "write"/"high_risk_write" while danger is false.

Common situations: Changing a tool's risk level after the fact without updating danger; copying _meta from another tool; adding the yes confirmation schema for high_risk_write but forgetting to set danger=true, or vice versa.

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