{"record":{"id":"8d451f3302bf9846","repo":"gastownhall/beads","slug":"edge-d-invalid-gate-q-valid-s-s","errorCode":null,"errorMessage":"edge %d: invalid gate %q (valid: %s, %s)","messagePattern":"edge (.+?): invalid gate %q \\(valid: (.+?), (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/graph_apply.go","lineNumber":616,"sourceCode":"\t\t}\n\t\tif edge.FromKey == \"\" && edge.FromID == \"\" {\n\t\t\treturn fmt.Errorf(\"edge %d: must specify from_key or from_id\", i)\n\t\t}\n\t\tif edge.ToKey == \"\" && edge.ToID == \"\" {\n\t\t\treturn fmt.Errorf(\"edge %d: must specify to_key or to_id\", i)\n\t\t}\n\t\tif edge.Type != \"\" {\n\t\t\tdt := types.DependencyType(edge.Type)\n\t\t\tif !dt.IsValid() {\n\t\t\t\treturn fmt.Errorf(\"edge %d: invalid dependency type %q\", i, edge.Type)\n\t\t\t}\n\t\t}\n\t\tif edge.Gate != \"\" || edge.SpawnerKey != \"\" || edge.SpawnerID != \"\" {\n\t\t\tif graphApplyDependencyType(edge.Type) != types.DepWaitsFor {\n\t\t\t\treturn fmt.Errorf(\"edge %d: gate/spawner fields require type %q\", i, types.DepWaitsFor)\n\t\t\t}\n\t\t\tif edge.Gate != \"\" && !types.IsValidWaitsForGate(edge.Gate) {\n\t\t\t\treturn fmt.Errorf(\"edge %d: invalid gate %q (valid: %s, %s)\", i, edge.Gate, types.WaitsForAllChildren, types.WaitsForAnyChildren)\n\t\t\t}\n\t\t\tif edge.SpawnerKey != \"\" && edge.SpawnerID != \"\" {\n\t\t\t\treturn fmt.Errorf(\"edge %d: cannot specify both spawner_key and spawner_id\", i)\n\t\t\t}\n\t\t\tif edge.SpawnerKey != \"\" && !seenKeys[edge.SpawnerKey] {\n\t\t\t\treturn fmt.Errorf(\"edge %d: spawner key %q not found in plan\", i, edge.SpawnerKey)\n\t\t\t}\n\t\t\t// Gate evaluation reads the spawner from the dependency target\n\t\t\t// (depends_on_id), not metadata, so the spawner must equal the to\n\t\t\t// endpoint. Since to_id overrides to_key at apply time\n\t\t\t// (resolveEdgeRef), a key-named spawner can't be combined with to_id.\n\t\t\tif edge.SpawnerKey != \"\" && edge.ToID != \"\" {\n\t\t\t\treturn 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)\n\t\t\t}\n\t\t\tif edge.SpawnerKey != \"\" && edge.SpawnerKey != edge.ToKey {\n\t\t\t\treturn fmt.Errorf(\"edge %d: spawner_key %q must match to_key %q (the waits-for target is the spawner)\", i, edge.SpawnerKey, edge.ToKey)\n\t\t\t}\n\t\t\tif edge.SpawnerID != \"\" && edge.SpawnerID != edge.ToID {","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/graph_apply.go#L598-L634","documentation":"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.","triggerScenarios":"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).","commonSituations":"Abbreviating gate names in hand-written plans; casing mistakes; plans produced before gate vocabulary stabilized.","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"],"exampleFix":"// before\n{\"type\": \"waits-for\", \"gate\": \"all\"}\n// after\n{\"type\": \"waits-for\", \"gate\": \"all-children\"}","handlingStrategy":"validation","validationCode":"var validGates = map[string]bool{\"all-children\": true, \"any-children\": true}\nif e.Gate != \"\" && !validGates[e.Gate] { return fmt.Errorf(\"invalid gate %q\", e.Gate) }","typeGuard":"func validGate(g string) bool { return types.IsValidWaitsForGate(g) }","tryCatchPattern":null,"preventionTips":["Use constants (WaitsForAllChildren / WaitsForAnyChildren) instead of string literals","Keep gate strings lowercase-hyphenated","Lint gate fields against the allowed set"],"tags":["graph-plan","waits-for","gate"],"backgroundTag":"invalid-waits-for-gate","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}