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
- Unwrap the error chain (%w wrapping) and read the innermost message — that is the actual failing formula.
- Fix the root cause in the named ancestor: break the cycle (1740) or repair/locate the missing parent (1741).
- 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
- Resolve top-level (base) formulas in CI so ancestor breakage is caught at its source.
- Avoid deep multi-level inheritance chains where a single failure cascades widely.
- Test each formula's resolution in isolation, not only the leaves.
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.