gastownhall/beads · error
edge %d: invalid gate %q (valid: %s, %s)
Error message
edge %d: invalid gate %q (valid: %s, %s)
What it means
For waits-for edges, the gate value must be one of the recognized gate types (all-children or any-children). Graph apply rejects unknown gate strings so gate evaluation at runtime never encounters an uninterpretable value.
Source
Thrown at cmd/bd/graph_apply.go:616
}
if edge.FromKey == "" && edge.FromID == "" {
return fmt.Errorf("edge %d: must specify from_key or from_id", i)
}
if edge.ToKey == "" && edge.ToID == "" {
return fmt.Errorf("edge %d: must specify to_key or to_id", i)
}
if edge.Type != "" {
dt := types.DependencyType(edge.Type)
if !dt.IsValid() {
return fmt.Errorf("edge %d: invalid dependency type %q", i, edge.Type)
}
}
if edge.Gate != "" || edge.SpawnerKey != "" || edge.SpawnerID != "" {
if graphApplyDependencyType(edge.Type) != types.DepWaitsFor {
return fmt.Errorf("edge %d: gate/spawner fields require type %q", i, types.DepWaitsFor)
}
if edge.Gate != "" && !types.IsValidWaitsForGate(edge.Gate) {
return fmt.Errorf("edge %d: invalid gate %q (valid: %s, %s)", i, edge.Gate, types.WaitsForAllChildren, types.WaitsForAnyChildren)
}
if edge.SpawnerKey != "" && edge.SpawnerID != "" {
return fmt.Errorf("edge %d: cannot specify both spawner_key and spawner_id", i)
}
if edge.SpawnerKey != "" && !seenKeys[edge.SpawnerKey] {
return fmt.Errorf("edge %d: spawner key %q not found in plan", i, edge.SpawnerKey)
}
// Gate evaluation reads the spawner from the dependency target
// (depends_on_id), not metadata, so the spawner must equal the to
// endpoint. Since to_id overrides to_key at apply time
// (resolveEdgeRef), a key-named spawner can't be combined with to_id.
if edge.SpawnerKey != "" && edge.ToID != "" {
return fmt.Errorf("edge %d: spawner_key %q cannot be combined with to_id %q (to_id overrides to_key as the waits-for target; use spawner_id)", i, edge.SpawnerKey, edge.ToID)
}
if edge.SpawnerKey != "" && edge.SpawnerKey != edge.ToKey {
return fmt.Errorf("edge %d: spawner_key %q must match to_key %q (the waits-for target is the spawner)", i, edge.SpawnerKey, edge.ToKey)
}
if edge.SpawnerID != "" && edge.SpawnerID != edge.ToID {View on GitHub (pinned to 71377f2769)
Solutions
- Set gate to exactly "all-children" or "any-children"
- Remove the gate field if default gating behavior is fine
- Grep the plan for gate values and validate them all before apply
Example fix
// before
{"type": "waits-for", "gate": "all"}
// after
{"type": "waits-for", "gate": "all-children"} Defensive patterns
Strategy: validation
Validate before calling
var validGates = map[string]bool{"all-children": true, "any-children": true}
if e.Gate != "" && !validGates[e.Gate] { return fmt.Errorf("invalid gate %q", e.Gate) } Type guard
func validGate(g string) bool { return types.IsValidWaitsForGate(g) } Prevention
- Use constants (WaitsForAllChildren / WaitsForAnyChildren) instead of string literals
- Keep gate strings lowercase-hyphenated
- Lint gate fields against the allowed set
When it happens
Trigger: An edge has type waits-for with a gate string not equal to types.WaitsForAllChildren or types.WaitsForAnyChildren (e.g. "all", "any", "ALL_CHILDREN", typo).
Common situations: Abbreviating gate names in hand-written plans; casing mistakes; plans produced before gate vocabulary stabilized.
Related errors
- edge %d: gate/spawner fields require type %q
- edge %d: cannot specify both spawner_key and spawner_id
- edge %d: spawner key %q not found in plan
- edge %d: spawner_key %q cannot be combined with to_id %q (to
- edge %d: spawner_key %q must match to_key %q (the waits-for
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/8d451f3302bf9846.
Report an issue: GitHub.