gastownhall/beads · error

get labels bulk: %w

Error message

get labels bulk: %w

What it means

This error wraps a failure from the label repository's bulk lookup (labelRepo.ListByIssueIDs) when fetching labels for multiple issues at once. The use-case layer (listBulk in internal/storage/domain/label.go) adds the 'get labels bulk:' prefix so the caller knows the failure happened during bulk label retrieval rather than a single-issue operation. The underlying cause is stored via %w and can be inspected with errors.Is/As.

Source

Thrown at internal/storage/domain/label.go:216

	}
	return out, nil
}

func (u *labelUseCaseImpl) GetLabelsForIssues(ctx context.Context, issueIDs []string) (map[string][]string, error) {
	return u.listBulk(ctx, issueIDs, false)
}

func (u *labelUseCaseImpl) GetLabelsForWisps(ctx context.Context, wispIDs []string) (map[string][]string, error) {
	return u.listBulk(ctx, wispIDs, true)
}

func (u *labelUseCaseImpl) listBulk(ctx context.Context, ids []string, useWisp bool) (map[string][]string, error) {
	if len(ids) == 0 {
		return map[string][]string{}, nil
	}
	out, err := u.labelRepo.ListByIssueIDs(ctx, ids, LabelOpts{UseWispsTable: useWisp})
	if err != nil {
		return nil, fmt.Errorf("get labels bulk: %w", err)
	}
	return out, nil
}

func (u *labelUseCaseImpl) InheritFromParent(ctx context.Context, childID, parentID, actor string, skipExisting []string) ([]string, error) {
	return u.inherit(ctx, childID, parentID, actor, skipExisting, false)
}

func (u *labelUseCaseImpl) InheritFromWispParent(ctx context.Context, childWispID, parentWispID, actor string, skipExisting []string) ([]string, error) {
	return u.inherit(ctx, childWispID, parentWispID, actor, skipExisting, true)
}

func (u *labelUseCaseImpl) inherit(ctx context.Context, childID, parentID, actor string, skipExisting []string, useWisp bool) ([]string, error) {
	if childID == "" {
		return nil, fmt.Errorf("inherit labels: childID must not be empty")
	}
	if parentID == "" {
		return nil, fmt.Errorf("inherit labels: parentID must not be empty")

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped cause with errors.Unwrap / %v of the error to see the underlying repository failure (connection, schema, context).
  2. Verify the database is reachable and not locked (close other bd processes, check the Dolt database files).
  3. If UseWispsTable is involved, confirm the wisps table exists / the database has been migrated.
  4. Retry with a fresh, non-canceled context; check for timeout/cancellation of the passed ctx.

Example fix

// before
labels, err := uc.GetLabelsForIssues(ctx, ids)
if err != nil { return err } // opaque wrap
// after
labels, err := uc.GetLabelsForIssues(ctx, ids)
if err != nil {
    if ctx.Err() != nil { return fmt.Errorf("canceled: %w", ctx.Err()) }
    return fmt.Errorf("bulk labels: %w", err) // log unwrapped cause
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling
if len(ids) == 0 { return map[string][]string{}, nil }
if ctx.Err() != nil { return ctx.Err() }

Try / catch

out, err := uc.GetLabelsForIssues(ctx, ids)
if err != nil {
    var ctxErr = ctx.Err()
    if ctxErr != nil { return fmt.Errorf("canceled: %w", ctxErr) }
    return fmt.Errorf("bulk labels: %w", err)
}

Prevention

When it happens

Trigger: Calling GetLabelsForIssues or GetLabelsForWisps with a non-empty ID list when the underlying repository query fails: database unavailable/corrupt, table missing, context canceled mid-query, or UseWispsTable routing to a missing/broken wisps table.

Common situations: Bulk-exporting issues where the Dolt database file is locked or the .beads database was partially migrated; running with a stale context after a timeout; querying wisps labels before the wisps table exists in an older database.

Related errors


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