gastownhall/beads · error · storage.ErrValidation
%w: create batch item %d requires an issue
Error message
%w: create batch item %d requires an issue
What it means
Validation error from ValidateCreateBatchRequest: every item in a CreateBatchRequest must carry a non-nil Issue pointer. It wraps storage.ErrValidation and runs before any transaction opens, so a batch refused here has provably written nothing. The library throws it to catch callers building batch items without assigning the issue payload.
Source
Thrown at internal/storage/issueops/create_batch.go:45
// ValidateCreateBatchRequest applies the request rules every BatchCreator
// implementation shares. It runs BEFORE any transaction opens: everything it
// checks is knowable from the request alone, so a batch refused here has
// provably written nothing.
//
// Per-item CONTENT rules are not here. They need the workspace's configured
// prefix, statuses and types, so they run inside the transaction through the
// same PreparePublicCreateRequest a single create runs.
func ValidateCreateBatchRequest(request publicops.CreateBatchRequest) error {
if request.Actor == "" {
return fmt.Errorf("%w: create batch requires an actor", storage.ErrValidation)
}
if len(request.Items) == 0 {
return fmt.Errorf("%w: create batch requires at least one item", storage.ErrValidation)
}
for i, item := range request.Items {
if item.Issue == nil {
return fmt.Errorf("%w: create batch item %d requires an issue", storage.ErrValidation, i)
}
}
return nil
}
// CreateBatchItemRequest projects one item onto the single-create request the
// shared preparation and validation speak. Both front doors and both bodies read
// an item through it, so no item restates CreateRequest's field rules.
func CreateBatchItemRequest(request publicops.CreateBatchRequest, item publicops.BatchCreateItem) publicops.CreateRequest {
return publicops.CreateRequest{
Actor: request.Actor,
Issue: item.Issue,
Dependencies: item.Dependencies,
ForceIDPrefix: request.ForceIDPrefix,
}
}
// CreateBatchItemError names the item a batch refusal came from. The roleView on GitHub (pinned to 71377f2769)
Solutions
- Find item index N named in the message and set its Issue field to a non-nil *types.Issue before calling ExecuteCreateBatch
- Filter nil issues out of the items slice before building the CreateBatchRequest
- Run ValidateCreateBatchRequest (or your own nil-check loop) client-side before invoking the batch
Example fix
// before
items := []publicops.BatchCreateItem{{Issue: &a}, {}}
// after
items := []publicops.BatchCreateItem{{Issue: &a}, {Issue: &b}} Defensive patterns
Strategy: validation
Validate before calling
for i, item := range req.Items {
if item.Issue == nil {
return fmt.Errorf("item %d has nil Issue", i)
}
}
// then call ExecuteCreateBatch Type guard
func hasIssue(item publicops.BatchCreateItem) bool { return item.Issue != nil } Prevention
- Build items through a constructor that requires a non-nil Issue
- Filter nil issues before batching
- Call ValidateCreateBatchRequest yourself first for fast-fail
When it happens
Trigger: Calling any BatchCreator's ExecuteCreateBatch with request.Items[i].Issue == nil — e.g. constructing BatchCreateItem{Issue: nil} or appending an item before filling its Issue field.
Common situations: Programmatically building batches from parsed input where an entry fails to map to an issue; partial struct initialization in loops; nil entries from a slice of optional issues not filtered before batching.
Related errors
- createMany[%d]: %w
- create batch item %d: %w
- mixed regular/wisp CreateIssues batch cannot include cross-b
- no store is open for this workspace
- not found
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/2b8c7a2b4a31e304.
Report an issue: GitHub.