gastownhall/beads · error

resolve parent %s: %w

Error message

resolve parent %s: %w

What it means

After successfully loading a parent, Resolve() recursively resolves it, and any error raised inside the parent's own resolution (including deeper ancestors, cycles, or var merge problems) is re-wrapped as 'resolve parent <name>: <cause>'. This adds the ancestor chain to the error so you can tell which level of the inheritance tree failed.

Source

Thrown at internal/formula/parser.go:244

		Version:     formula.Version,
		Type:        formula.Type,
		Source:      formula.Source,
		Vars:        make(map[string]*VarDef),
		Steps:       nil,
		Compose:     nil,
	}

	// Apply each parent in order
	for _, parentName := range formula.Extends {
		parent, err := p.loadFormula(parentName)
		if err != nil {
			return nil, fmt.Errorf("extends %s: %w", parentName, err)
		}

		// Resolve parent recursively
		parent, err = p.Resolve(parent)
		if err != nil {
			return nil, fmt.Errorf("resolve parent %s: %w", parentName, err)
		}

		// Merge parent vars (parent vars are inherited, child overrides)
		for name, varDef := range parent.Vars {
			if _, exists := merged.Vars[name]; !exists {
				merged.Vars[name] = varDef
			}
		}

		// Merge parent steps (append, child steps come after)
		merged.Steps = append(merged.Steps, parent.Steps...)

		// Merge parent compose rules
		merged.Compose = mergeComposeRules(merged.Compose, parent.Compose)
	}

	// Apply child overrides
	for name, varDef := range formula.Vars {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Unwrap the error chain (%w wrapping) and read the innermost message — that is the actual failing formula.
  2. Fix the root cause in the named ancestor: break the cycle (1740) or repair/locate the missing parent (1741).
  3. Run Resolve on the suspect ancestor formula directly to reproduce the failure in isolation.

Example fix

# before: child.md -> mid.md -> base.md (base.md extends mid.md)
# error: resolve parent mid: resolve parent base: circular extends detected: ...

# after: remove 'extends: [mid]' from base.md so the chain terminates
Defensive patterns

Strategy: try-catch

Validate before calling

// Resolve each ancestor individually first to isolate the failure.
for _, name := range ancestry(f) {
	if pf, err := p.LoadByName(name); err == nil {
		if _, err := p.Resolve(pf); err != nil {
			return fmt.Errorf"ancestor %s is broken: %w", name, err
		}
	}
}

Try / catch

if _, err := p.Resolve(f); err != nil {
	// %w chain: print err and unwrap until the root cause
	for e := err; e != nil; e = errors.Unwrap(e) {
		log.Println(e)
	}
}

Prevention

When it happens

Trigger: Calling Resolve on a child formula when an ancestor in its extends graph fails Resolve — e.g. a grandparent has a circular extends (1740) or a great-grandparent cannot be loaded (1741). The root cause appears innermost in the wrapped chain.

Common situations: Multi-level inheritance chains (base -> mid -> child) where a rename or deletion happened at the top of the chain; debugging is confusing because the failure surfaces at the child even though the broken file is an ancestor.

Related errors


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