gastownhall/beads · error

inline expand on step

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.

Solutions

  1. 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).
  2. 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.
  3. Set GT_ROOT or place the formula in the repo's .beads/formulas directory so shared formulas resolve.
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/80c40a7d06d2c519. Report an issue: GitHub.

Appendix: 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)