{"record":{"id":"68df0b269dd6e9c6","repo":"gastownhall/beads","slug":"applying-gates-w","errorCode":null,"errorMessage":"applying gates: %w","messagePattern":"applying gates: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/formula/controlflow.go","lineNumber":572,"sourceCode":"\n\t// Apply loops first (expands steps) - ApplyLoops already returns new slice\n\tsteps, err = ApplyLoops(steps)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"applying loops: %w\", err)\n\t}\n\n\t// Build stepMap once for branches and gates\n\t// No need to clone here since ApplyLoops already returned a new slice\n\tstepMap := buildStepMap(steps)\n\n\t// Apply branches (wires dependencies)\n\tif err := applyBranchesWithMap(stepMap, compose); err != nil {\n\t\treturn nil, fmt.Errorf(\"applying branches: %w\", err)\n\t}\n\n\t// Apply gates (adds labels)\n\tif err := applyGatesWithMap(stepMap, compose); err != nil {\n\t\treturn nil, fmt.Errorf(\"applying gates: %w\", err)\n\t}\n\n\treturn steps, nil\n}\n\n// cloneStepDeep creates a deep copy of a step including children.\nfunc cloneStepDeep(s *Step) *Step {\n\tclone := cloneStep(s)\n\n\tif len(s.Children) > 0 {\n\t\tclone.Children = make([]*Step, len(s.Children))\n\t\tfor i, child := range s.Children {\n\t\t\tclone.Children[i] = cloneStepDeep(child)\n\t\t}\n\t}\n\n\treturn clone\n}","sourceCodeStart":554,"sourceCodeEnd":590,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/formula/controlflow.go#L554-L590","documentation":"ApplyControlFlow wraps failures from applyGatesWithMap with 'applying gates: %w'. Gate rules attach a 'gate:<condition>' label to a target step, evaluated at runtime by the patrol executor. This error means a gate rule is missing 'before' or 'condition', its condition fails ParseCondition syntax validation, or the 'before' target step ID does not exist.","triggerScenarios":"Calling ApplyControlFlow(steps, compose) where a compose.Gate entry has an empty Before or Condition, a condition string that ParseCondition rejects, or a Before step ID absent from the step map.","commonSituations":"Malformed gate condition expressions in formula YAML (bad comparison syntax); gate targeting a step renamed or consumed by a prior expansion; copy-pasted gate rules referencing steps from a different formula.","solutions":["Read the wrapped inner error to see which gate rule failed and why (missing field, invalid condition, or unknown target)","Validate the condition syntax independently with ParseCondition(gate.Condition) and fix the expression","Confirm the gate's Before step ID exists in the formula, including steps produced by loop expansion","Correct or remove the invalid gate rule in the compose section"],"exampleFix":"// before\ngates:\n  - before: deploy\n    condition: env ==\n// after\ngates:\n  - before: deploy\n    condition: env == \"prod\"","handlingStrategy":"validation","validationCode":"for _, g := range compose.Gate {\n\tif g.Before == \"\" || g.Condition == \"\" {\n\t\treturn fmt.Errorf(\"gate rule requires before and condition\")\n\t}\n\tif _, err := ParseCondition(g.Condition); err != nil {\n\t\treturn fmt.Errorf(\"gate condition %q invalid: %w\", g.Condition, err)\n\t}\n\tif _, ok := buildStepMap(steps)[g.Before]; !ok {\n\t\treturn fmt.Errorf(\"gate target %q not found\", g.Before)\n\t}\n}","typeGuard":null,"tryCatchPattern":"out, err := ApplyControlFlow(steps, compose)\nif err != nil {\n\tvar gateErr error\n\tif strings.Contains(err.Error(), \"applying gates\") && errors.Unwrap(err) != nil {\n\t\tgateErr = errors.Unwrap(err)\n\t}\n\treturn fmt.Errorf(\"gate rule rejected: %w\", errors.Join(err, gateErr))\n}","preventionTips":["Pre-validate gate conditions with ParseCondition during formula authoring","Lint gate Before targets against step IDs in CI","Quote string values inside condition expressions to avoid parse ambiguity","Re-check gates after any change that renames or expands steps"],"tags":["go","formula","control-flow","gate-condition"],"backgroundTag":"invalid-gate-condition","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}