gastownhall/beads · error

step %s not found

Error message

step %s not found

What it means

The molecule step-advance transaction looks up the step issue by ID inside a Dolt transaction and requires it to exist. When `tx.GetIssue` returns nil (the ID does not correspond to any issue), the port layer converts that into a formatted `step %s not found` error so the caller knows the molecule step ID was wrong.

Source

Thrown at cmd/bd/mol_port.go:107

// store, which opens a second pool connection — a deadlock when
// MaxOpenConns=1 and the transaction already holds the only one. It also
// keeps the read consistent with any config written earlier in the same
// transaction rather than seeing the last committed value.
func (w storeMolWriter) GetConfig(ctx context.Context, key string) (string, error) {
	if w.tx != nil {
		return w.tx.GetConfig(ctx, key)
	}
	return w.DoltStorage.GetConfig(ctx, key)
}

func (w storeMolWriter) ClaimStepIfOpen(ctx context.Context, id, actor string) error {
	return w.DoltStorage.RunInTransaction(ctx, fmt.Sprintf("bd: advance to step %s", id), func(tx storage.Transaction) error {
		current, err := tx.GetIssue(ctx, id)
		if err != nil {
			return err
		}
		if current == nil {
			return fmt.Errorf("step %s not found", id)
		}
		if current.Status != types.StatusOpen {
			return fmt.Errorf("step %s already claimed (status: %s)", id, current.Status)
		}
		return tx.UpdateIssue(ctx, id, map[string]interface{}{"status": types.StatusInProgress}, actor)
	})
}

func newStandaloneStoreMolWriter(store storage.DoltStorage) storeMolWriter {
	return storeMolWriter{DoltStorage: store}
}

type uowMolReader struct {
	uw uow.UnitOfWork
}

func (r uowMolReader) GetIssue(ctx context.Context, id string) (*types.Issue, error) {
	issue, isWisp, rerr := workapi.GetIssueOrWisp(ctx, workapi.NewUOWDetailSource(r.uw), id)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the step ID with `bd show <id>` (or `bd list`) and correct any typo.
  2. List the molecule's actual steps (`bd mol progress <molecule>`) and use one of those IDs.
  3. Confirm you are operating on the same database/workspace that contains the molecule.

Example fix

// before
err := writer.AdvanceToStep(ctx, "bd-9999", actor)   // id typo
// after
err := writer.AdvanceToStep(ctx, "bd-1234", actor)   // verified step id
Defensive patterns

Strategy: validation

Validate before calling

// shell: confirm the step exists before advancing
bd show "$STEP_ID" --json >/dev/null 2>&1 || { echo "step $STEP_ID does not exist"; exit 1; }
# then invoke the advance/claim step via your mol workflow

Type guard

func stepExists(ctx context.Context, r MolReader, id string) bool {
	iss, err := r.GetIssue(ctx, id)
	return err == nil && iss != nil
}

Try / catch

if err := advance(ctx, stepID, actor); err != nil && strings.Contains(err.Error(), "not found") {
	return fmt.Errorf("step id %q invalid: %w", stepID, err)
}

Prevention

When it happens

Trigger: Calling the molecule port's advance/claim operation with an issue ID that does not exist in the database — e.g. a typo'd step ID, an ID from another database, or a deleted/wisp-routed issue. `GetIssue` returns nil inside the `RunInTransaction` callback and the error is raised.

Common situations: Copy-pasting an ID with a typo; referencing a step that was closed and cleaned up; pointing at a different workspace/database than the one containing the molecule; stale scripts holding IDs from a re-created molecule.

Related errors


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