gastownhall/beads · error
inline expand on step %q: loading %q: %w
Error message
inline expand on step %q: loading %q: %w
What it means
Thrown when a step's Expand field names a formula that parser.LoadByName cannot find or load. The underlying load error (not found, unreadable file, parse failure) is wrapped with %w so the root cause appears in the message. It means the inline expansion reference cannot be resolved against the configured formula search paths.
Source
Thrown at internal/formula/expand.go:472
return applyInlineExpansionsRecursive(steps, parser, 0)
}
// applyInlineExpansionsRecursive handles inline expansions for a slice of steps.
// depth tracks recursion to prevent infinite expansion loops.
func applyInlineExpansionsRecursive(steps []*Step, parser *Parser, depth int) ([]*Step, error) {
if depth > DefaultMaxExpansionDepth {
return nil, fmt.Errorf("inline expansion depth limit exceeded: max %d levels", DefaultMaxExpansionDepth)
}
var result []*Step
for _, step := range steps {
// Check if this step has an inline expansion
if step.Expand != "" {
// Load the expansion formula
expFormula, err := parser.LoadByName(step.Expand)
if err != nil {
return nil, fmt.Errorf("inline expand on step %q: loading %q: %w", step.ID, step.Expand, err)
}
if expFormula.Type != TypeExpansion {
return nil, fmt.Errorf("inline expand on step %q: %q is not an expansion formula (type=%s)",
step.ID, step.Expand, expFormula.Type)
}
if len(expFormula.Template) == 0 {
return nil, fmt.Errorf("inline expand on step %q: %q has no template steps", step.ID, step.Expand)
}
// Merge formula default vars with step's ExpandVars overrides
vars := mergeVars(expFormula, step.ExpandVars)
// Expand the step using the template (reuse existing expandStep)
expandedSteps, err := expandStep(step, expFormula.Template, 0, vars)
if err != nil {
return nil, fmt.Errorf("inline expand on step %q: %w", step.ID, err)View on GitHub (pinned to 71377f2769)
Solutions
- Verify the Expand name exactly matches the formula's `formula` field and that its file exists under one of the search paths (.beads/formulas, ~/.beads/formulas, $GT_ROOT/.beads/formulas).
- Read the wrapped root-cause error: if it's a parse/read error, fix the formula file itself; if 'not found', add or correct the file location.
- Set GT_ROOT or place the formula in the repo's .beads/formulas directory so shared formulas resolve.
- Run bd formula listing to confirm the formula is discoverable by the parser.
Example fix
// before [[step]] id = "scaffold" expand = "scafolding" # typo: formula not found // after [[step]] id = "scaffold" expand = "scaffolding" # matches .beads/formulas/scaffolding.formula.toml
Defensive patterns
Strategy: validation
Validate before calling
for _, s := range steps {
if s.Expand == "" {
continue
}
if _, err := parser.LoadByName(s.Expand); err != nil {
return fmt.Errorf("step %q references unknown expansion %q: %w", s.ID, s.Expand, err)
}
} Type guard
func hasResolvableExpand(p *formula.Parser, s *formula.Step) bool {
if s.Expand == "" {
return true
}
_, err := p.LoadByName(s.Expand)
return err == nil
} Try / catch
expanded, err := formula.ApplyInlineExpansions(steps, parser)
if err != nil {
var pathErr *fs.PathError
if errors.As(err, &pathErr) && os.IsNotExist(pathErr) {
return fmt.Errorf("formula referenced by Expand is missing: %w", err)
}
return err
} Prevention
- Commit all referenced formula files under .beads/formulas so every checkout has them.
- Spell-check Expand names against the formula's `formula` field; keep names and filenames consistent.
- Add a CI lint that loads every formula and resolves every Expand reference.
When it happens
Trigger: ApplyInlineExpansions encounters step.Expand set to a name with no matching formula file in any search path (.beads/formulas in repo, ~/.beads/formulas, GT_ROOT), or the formula file exists but fails to load (unreadable, unparseable).
Common situations: Typo in the Expand value; formula file not committed or missing from a checkout; formula defined in a search path not configured (GT_ROOT unset); formula file has a syntax error so LoadByName's parse fails.
Related errors
- inline expansion depth limit exceeded: max %d levels
- inline expand on step %q: %q is not an expansion formula (ty
- formula %q not found in search paths
- parsing formula: %w
- applying inline expansions: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/80c40a7d06d2c519.
Report an issue: GitHub.