gastownhall/beads · error

neither '%s' nor '%s' found in epic text

Error message

neither '%s' nor '%s' found in epic text

What it means

After `parseDistillVar` splits the `--var` flag into a left and right side, at least one side must literally appear in the epic's searchable text so the command can decide which side is the variable name. If neither the left nor the right string is found in the epic text, the flag is ambiguous/invalid and distillation aborts.

Source

Thrown at cmd/bd/mol_distill.go:101

	left, right := parts[0], parts[1]
	leftFound := strings.Contains(searchableText, left)
	rightFound := strings.Contains(searchableText, right)

	switch {
	case rightFound && !leftFound:
		// spawn-style: --var branch=feature-auth
		// left is variable name, right is the value to find
		return right, left, nil
	case leftFound && !rightFound:
		// substitution-style: --var feature-auth=branch
		// left is value to find, right is variable name
		return left, right, nil
	case leftFound && rightFound:
		// Both found - prefer spawn-style (more natural guess)
		// Agent likely typed: --var varname=concrete_value
		return right, left, nil
	default:
		return "", "", fmt.Errorf("neither '%s' nor '%s' found in epic text", left, right)
	}
}

type molDistillInput struct {
	epicID         string
	formulaNameArg string
	varFlags       []string
	dryRun         bool
	outputDir      string
}

func gatherMolDistillInput(cmd *cobra.Command, args []string) molDistillInput {
	in := molDistillInput{epicID: args[0]}
	in.varFlags, _ = cmd.Flags().GetStringArray("var")
	in.dryRun, _ = cmd.Flags().GetBool("dry-run")
	in.outputDir, _ = cmd.Flags().GetString("output")
	if len(args) > 1 {
		in.formulaNameArg = args[1]

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the epic (`bd show <epic-id>`) and use an exact substring of its text on one side of the `=`.
  2. Fix typos or case differences so one side of the flag matches text in the epic verbatim.
  3. Use the spawn-style `variable=value` form with an existing value, e.g. `--var epic_name=<exact text from epic>`.

Example fix

// before
bd mol distill --epic bd-42 --var epic_name=AutH Refactor
// after
bd mol distill --epic bd-42 --var epic_name=Auth Refactor   // exact text from the epic
Defensive patterns

Strategy: validation

Validate before calling

// shell: ensure one side of --var exists in the epic text before invoking
EPIC=$(bd show bd-42 --json | jq -r '.title + " " + .description')
VAR='epic_name=Auth Refactor'
L=${VAR%%=*}; R=${VAR#*=}
[[ "$EPIC" == *"$L"* || "$EPIC" == *"$R"* ]] || { echo "neither side found in epic text"; exit 1; }
bd mol distill --epic bd-42 --var "$VAR"

Type guard

func varSideFound(flag, epicText string) bool {
	p := strings.SplitN(flag, "=", 2)
	if len(p) != 2 {
		return false
	}
	return strings.Contains(epicText, p[0]) || strings.Contains(epicText, p[1])
}

Try / catch

if err := runDistill(); err != nil && strings.Contains(err.Error(), "neither") {
	fmt.Fprintln(os.Stderr, "use text that appears verbatim in the epic")
}

Prevention

When it happens

Trigger: Running `bd mol distill --var 'foo=bar'` (from `distillSubgraph`) where neither `foo` nor `bar` occurs anywhere in the target epic's title/description text. Both `leftFound` and `rightFound` are false, so the `default` branch returns this error.

Common situations: Typos between the flag value and the epic text; the epic was renamed/edited after the command line was scripted; case mismatch (text search is case-sensitive); passing a variable name that only exists in your head, not in the epic content.

Related errors


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