gastownhall/beads · error

reopen: actor must not be empty

Error message

reopen: actor must not be empty

What it means

A guard error thrown by the reopen() use case when the actor argument is empty. Reopen events are attributed to an actor, so the library rejects empty identities to keep the audit trail meaningful.

Source

Thrown at internal/storage/domain/issue.go:1715

		Issue:  issue,
		Closed: !row.AlreadyClosed,
	}, nil
}

func (u *issueUseCaseImpl) ReopenIssue(ctx context.Context, id string, params ReopenIssueParams, actor string) (ReopenIssueResult, error) {
	return u.reopen(ctx, id, params, actor, false)
}

func (u *issueUseCaseImpl) ReopenWisp(ctx context.Context, id string, params ReopenIssueParams, actor string) (ReopenIssueResult, error) {
	return u.reopen(ctx, id, params, actor, true)
}

func (u *issueUseCaseImpl) reopen(ctx context.Context, id string, params ReopenIssueParams, actor string, useWisp bool) (ReopenIssueResult, error) {
	if id == "" {
		return ReopenIssueResult{}, fmt.Errorf("reopen: id must not be empty")
	}
	if actor == "" {
		return ReopenIssueResult{}, fmt.Errorf("reopen: actor must not be empty")
	}
	row, err := u.issueRepo.Reopen(ctx, id, ReopenRowParams{Reason: params.Reason}, actor, IssueTableOpts{UseWispsTable: useWisp})
	if err != nil {
		return ReopenIssueResult{}, fmt.Errorf("reopen %s: %w", id, err)
	}
	issue, err := u.issueRepo.Get(ctx, id, IssueTableOpts{UseWispsTable: row.IsWisp})
	if err != nil {
		return ReopenIssueResult{}, fmt.Errorf("reopen %s: reload: %w", id, err)
	}
	return ReopenIssueResult{
		Issue:    issue,
		Reopened: row.Updated,
	}, nil
}

func (u *issueUseCaseImpl) ClaimIssueIfOpen(ctx context.Context, id, actor string) (ClaimResult, error) {
	return u.claim(ctx, id, actor, false)
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Pass a non-empty actor (authenticated user, service account, or 'system' default).
  2. Set the identity-providing environment variable in the runtime context.
  3. Validate actor before the call and surface a clear configuration error.

Example fix

// before
usecase.ReopenIssue(ctx, id, params, "")
// after
if actor == "" { actor = "automation@service" }
usecase.ReopenIssue(ctx, id, params, actor)
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(actor) == "" {
    return fmt.Errorf("reopen: actor must not be empty")
}

Type guard

func validActor(a string) bool { return strings.TrimSpace(a) != "" }

Try / catch

if err := run(); err != nil {
    if strings.Contains(err.Error(), "actor must not be empty") {
        return fmt.Errorf("configure an actor identity before reopening")
    }
    return err
}

Prevention

When it happens

Trigger: Calling ReopenIssue / ReopenWisp with actor="" — e.g. missing identity in a headless environment, an integration that forgot to pass the actor through, or an empty default in a wrapper function.

Common situations: CI jobs without user identity env vars; service scripts calling reopen with a hardcoded empty actor; webhooks forwarding payloads that omit the acting user.

Related errors


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