gastownhall/beads · error · publicCreateValidationError

create: actor and issue are required

Error message

create: actor and issue are required

What it means

ValidatePublicCreateRequest requires a create request to carry both a non-empty Actor and a non-nil Issue. Without them nothing meaningful can be created, so the request is rejected with a wrapped validation error (publicCreateValidationError) before any database work or unit-of-work is opened.

Source

Thrown at internal/storage/issueops/public_create.go:29

	"github.com/steveyegge/beads/internal/storage/domain"
	"github.com/steveyegge/beads/internal/types"
	publicops "github.com/steveyegge/beads/issueops"
)

// PublicCreateContext holds the configuration required to prepare a public
// create request for the domain create use case.
type PublicCreateContext struct {
	IssuePrefix     string
	AllowedPrefixes string
	CustomStatuses  []string
	CustomTypes     []string
}

// ValidatePublicCreateRequest checks public-create invariants independent of
// database configuration.
func ValidatePublicCreateRequest(request publicops.CreateRequest) error {
	if request.Actor == "" || request.Issue == nil {
		return publicCreateValidationError(fmt.Errorf("create: actor and issue are required"))
	}
	if err := types.CheckFieldLen("actor", request.Actor); err != nil {
		return publicCreateValidationError(fmt.Errorf("create: %w", err))
	}
	if len(request.Issue.Comments) > 0 || len(request.Issue.Dependencies) > 0 {
		return publicCreateValidationError(fmt.Errorf("create: issue comments and dependencies must be supplied through request fields"))
	}
	for _, field := range []struct{ name, value string }{{"assignee", request.Issue.Assignee}, {"owner", request.Issue.Owner}} {
		if err := types.CheckFieldLen(field.name, field.value); err != nil {
			return publicCreateValidationError(err)
		}
	}
	for _, label := range request.Issue.Labels {
		if err := types.CheckFieldLen("label", label); err != nil {
			return publicCreateValidationError(err)
		}
	}
	if err := types.CheckFieldLen("parent ID", request.ParentID); err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Set request.Actor to the acting identity and request.Issue to a non-nil *types.Issue before calling
  2. Fail fast in the CLI layer with usage guidance when actor or issue payload is absent
  3. Trim the actor and check Issue != nil in caller code before building the request

Example fix

// before
req := publicops.CreateRequest{Actor: actor} // Issue never set
// after
if issue == nil || actor == "" {
    return fmt.Errorf("create requires an actor and an issue")
}
req := publicops.CreateRequest{Actor: actor, Issue: issue}
Defensive patterns

Strategy: validation

Validate before calling

func createRequestOK(r publicops.CreateRequest) bool { return r.Actor != "" && r.Issue != nil }

Try / catch

if err != nil {
  var valErr *storage.ValidationError
  if errors.As(err, &valErr) || errors.Is(err, storage.ErrValidation) {
    return fmt.Errorf("bad create request: %w", err)
  }
  return err
}

Prevention

When it happens

Trigger: Calling ExecuteCreate or PreparePublicCreateRequest with CreateRequest{Actor: ""} or CreateRequest{Issue: nil}.

Common situations: Unset actor from missing config/env; constructing the request where the Issue struct is conditionally built and ends up nil; a CLI path where neither --actor nor issue JSON was supplied.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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