gastownhall/beads · error

ErrCloseBlocked

ErrCloseBlocked

Error message

cannot close blocked issue

What it means

ErrCloseBlocked is returned by CloseIssueChecked when an issue cannot be closed because it is still blocked: is_blocked=1 due to an open blocking dependency or an open blocking gate. Bypass with CloseIssueOptions.Force. Batch closer paths surface it as a per-item refusal while survivors commit.

Source

Thrown at issueops/errors.go:104

// invalid, a row can be missing and a database can be uninitialized on any
// plane. The refusals BELOW that name issue concepts stay here.
var (
	// ErrNotFound is returned when a requested entity does not exist in the database.
	ErrNotFound = beadserrors.ErrNotFound
	// ErrValidation classifies deterministic request-validation failures.
	ErrValidation = beadserrors.ErrValidation
	// ErrNotInitialized is returned when the database has not been initialized
	// (e.g., issue_prefix config is missing).
	ErrNotInitialized = beadserrors.ErrNotInitialized
)

// ErrPrefixMismatch is returned when an issue ID does not match the configured prefix.
var ErrPrefixMismatch = errors.New("prefix mismatch")

// ErrCloseBlocked is returned by CloseIssueChecked when an issue cannot be
// closed because it is still blocked (is_blocked=1: an open blocking dependency
// or an open blocking gate). Bypass with CloseIssueOptions.Force.
var ErrCloseBlocked = errors.New("cannot close blocked issue")

// ErrCloseOpenChildren is returned when an unforced close finds open
// parent-child dependents.
var ErrCloseOpenChildren = errors.New("cannot close issue with open children")

// CloseOpenChildrenError reports the issue and open-child count that refused a
// guarded close.
type CloseOpenChildrenError struct {
	IssueID      string
	OpenChildren int
}

func (e *CloseOpenChildrenError) Error() string {
	return fmt.Sprintf("cannot close %s: %d open child issue(s); close children first or use --force to override", e.IssueID, e.OpenChildren)
}

// Unwrap makes CloseOpenChildrenError match ErrCloseOpenChildren.
func (e *CloseOpenChildrenError) Unwrap() error {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Close or resolve the open blocking dependencies/gates first, then retry the close.
  2. Pass CloseIssueOptions.Force = true to deliberately close the blocked issue.
  3. Inspect the issue's dependencies (bd dep list) to find what is blocking it.
  4. In batch closes, handle the per-item refusal and let survivors commit rather than failing the whole batch.

Example fix

// before
err := ops.CloseIssueChecked(ctx, id, types.CloseIssueOptions{}) // blocked

// after
err := ops.CloseIssueChecked(ctx, id, types.CloseIssueOptions{Force: true})
// or resolve blockers first, then close without Force
Defensive patterns

Strategy: validation

Validate before calling

iss, _ := store.GetIssue(ctx, id)
if iss.IsBlocked {
    // resolve open blocking dependencies/gates before closing
}

Try / catch

if errors.Is(err, issueops.ErrCloseBlocked) {
    // list blockers for the user or retry with CloseIssueOptions.Force
}

Prevention

When it happens

Trigger: Calling CloseIssueChecked (or lifecycle close / batch close) on an issue with is_blocked=1; the issue has an open blocking dependency or an open blocking gate; transitively blocked targets in lifecycle close flows.

Common situations: Closing a parent/epic whose blocker children are still open; forgetting to finish dependency work first; batch scripts closing everything without checking dependency state; gates (external conditions) still open.

Related errors


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