gastownhall/beads · error
branch: from is required
Error message
branch: from is required
What it means
applyBranchesWithMap validates each ComposeRules branch rule and requires a From step ID identifying where the branch fan-out begins. An empty From makes the branch rule unusable, so ApplyBranches/ApplyControlFlow fails before modifying the step graph.
Source
Thrown at internal/formula/controlflow.go:446
if err := applyBranchesWithMap(stepMap, compose); err != nil {
return nil, err
}
return cloned, nil
}
// applyBranchesWithMap applies branch rules using a pre-built stepMap.
// This is the internal implementation used by both ApplyBranches and ApplyControlFlow.
// The stepMap entries are modified in place.
func applyBranchesWithMap(stepMap map[string]*Step, compose *ComposeRules) error {
if compose == nil || len(compose.Branch) == 0 {
return nil
}
for _, branch := range compose.Branch {
// Validate the branch rule
if branch.From == "" {
return fmt.Errorf("branch: from is required")
}
if len(branch.Steps) == 0 {
return fmt.Errorf("branch: steps is required")
}
if branch.Join == "" {
return fmt.Errorf("branch: join is required")
}
// Verify all steps exist
if _, ok := stepMap[branch.From]; !ok {
return fmt.Errorf("branch: from step %q not found", branch.From)
}
if _, ok := stepMap[branch.Join]; !ok {
return fmt.Errorf("branch: join step %q not found", branch.Join)
}
for _, stepID := range branch.Steps {
if _, ok := stepMap[stepID]; !ok {
return fmt.Errorf("branch: parallel step %q not found", stepID)View on GitHub (pinned to 71377f2769)
Solutions
- Add the missing `from:` key naming the fan-out step in the formula's branch rule
- Check YAML indentation so the branch entry actually contains its from field
- Ensure the field name matches the schema (from, not source/start)
Example fix
# before
branch:
- steps: [a, b]
join: c
# after
branch:
- from: start
steps: [a, b]
join: c Defensive patterns
Strategy: validation
Validate before calling
for i, b := range compose.Branch {
if b.From == "" {
return fmt.Errorf("branch[%d]: from is required", i)
}
} Try / catch
steps, err := formula.ApplyBranches(steps, compose)
if err != nil {
if strings.Contains(err.Error(), "from is required") {
return fmt.Errorf("compose branch missing 'from': %w", err)
}
return err
} Prevention
- Always include from/steps/join in every branch rule
- Lint formula YAML against the compose schema before loading
- Watch for YAML indentation that silently drops nested keys
When it happens
Trigger: Calling ApplyBranches(steps, compose) or ApplyControlFlow with a compose.Branch entry whose From field is empty/omitted in the formula's compose section.
Common situations: YAML branch block missing the `from:` key; indentation error placing the rule under the wrong parent; building ComposeRules programmatically and forgetting to set From.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- branch: steps is required
- branch: join is required
- branch: from step %q not found
- branch: join step %q not found
- applying expansions: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0457f8805705a4a5.
Report an issue: GitHub.