larksuite/cli · error
Input.Relations[%d].Stage %q is invalid
Error message
Input.Relations[%d].Stage %q is invalid
What it means
compileRelations requires each relation's Stage to be typedStageSourcePreRun or typedStageAfterPrepare; anything else is rejected at compile time. Stage decides when the relation check runs (against raw CLI source flags or after the prepare phase), so an invalid stage would leave enforcement timing undefined.
Source
Thrown at shortcuts/common/typed_compile_contract.go:33
seen := make(map[string]struct{})
for i, definition := range definitions {
minimum := 2
exact := 0
switch definition.Kind {
case typedRelationExactlyOne, typedRelationAtLeastOne, typedRelationCoOccur, typedRelationConflicts:
case typedRelationRequires:
exact = 2
default:
return nil, fmt.Errorf("Input.Relations[%d].Kind %q is invalid", i, definition.Kind)
}
if exact > 0 && len(definition.Params) != exact || exact == 0 && len(definition.Params) < minimum {
return nil, fmt.Errorf("Input.Relations[%d] kind %s has invalid param count %d", i, definition.Kind, len(definition.Params))
}
if definition.Presence != typedPresenceExplicit && definition.Presence != typedPresenceNonZero {
return nil, fmt.Errorf("Input.Relations[%d].Presence %q is invalid", i, definition.Presence)
}
if definition.Stage != typedStageSourcePreRun && definition.Stage != typedStageAfterPrepare {
return nil, fmt.Errorf("Input.Relations[%d].Stage %q is invalid", i, definition.Stage)
}
compiled := compiledRelation{kind: definition.Kind, presence: definition.Presence, stage: definition.Stage}
local := make(map[string]struct{})
for _, name := range definition.Params {
field, ok := fieldByName[name]
if !ok {
return nil, fmt.Errorf("Input.Relations[%d] references unknown param --%s", i, name)
}
if _, duplicate := local[name]; duplicate {
return nil, fmt.Errorf("Input.Relations[%d] repeats param --%s", i, name)
}
local[name] = struct{}{}
compiled.fields = append(compiled.fields, field)
}
keyBytes, _ := json.Marshal(definition)
key := string(keyBytes)
if _, duplicate := seen[key]; duplicate {
return nil, fmt.Errorf("Input.Relations[%d] duplicates an earlier relation", i)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Set Stage to typedStageSourcePreRun or typedStageAfterPrepare explicitly
- Choose source_pre_run for checks on raw flags, after_prepare for checks that depend on prepared state
- Update any definitions copied from older code that used a different stage value
Example fix
// before
{Kind: typedRelationAtLeastOne, Params: []string{"a","b"}, Stage: ""}
// after
{Kind: typedRelationAtLeastOne, Params: []string{"a","b"}, Stage: typedStageSourcePreRun} Defensive patterns
Strategy: validation
Validate before calling
func knownStage(s typedStage) bool {
return s == typedStageSourcePreRun || s == typedStageAfterPrepare
} Type guard
func isTypedStage(v any) bool {
s, ok := v.(typedStage)
return ok && knownStage(s)
} Prevention
- Always set Stage explicitly when building typedRelation literals
- Use typedStageSourcePreRun for raw-flag checks and typedStageAfterPrepare for prepared-state checks
- Add a compile test asserting Stage on every declared relation
When it happens
Trigger: Setting Stage to an empty string (struct zero value) or an unknown string like "pre-run" in a typedRelation declaration.
Common situations: Omitting Stage when constructing relations literally; renaming or misremembering stage constants across versions.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Input.Relations[%d].Kind %q is invalid
- Input.Relations[%d] kind %s has invalid param count %d
- Input.Relations[%d].Presence %q is invalid
- Input.Relations[%d] references unknown param --%s
- Invalid column: {column!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/0849ac5a73d6e350.
Report an issue: GitHub.