{"record":{"id":"2dfe561d3fdd8ddc","repo":"gastownhall/beads","slug":"w-apply-batch-item-d-requires-an-issue","errorCode":null,"errorMessage":"%w: apply batch item %d requires an issue","messagePattern":"%w: apply batch item (.+?) requires an issue","errorType":"validation","errorClass":"issueops.ErrValidation","httpStatus":null,"severity":"error","filePath":"internal/storage/batch_apply.go","lineNumber":147,"sourceCode":"\t\t\tmatches = item.Create != nil\n\t\tcase issueops.ItemUpdate:\n\t\t\tmatches = item.Update != nil\n\t\tcase issueops.ItemClose:\n\t\t\tmatches = item.Close != nil\n\t\tcase issueops.ItemDepAdd:\n\t\t\tmatches = item.DepAdd != nil\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"%w: apply batch item %d has unknown kind %q\", issueops.ErrValidation, i, item.Kind)\n\t\t}\n\t\tif !matches {\n\t\t\treturn nil, fmt.Errorf(\"%w: apply batch item %d is kind %q but carries another kind's payload\",\n\t\t\t\tissueops.ErrValidation, i, item.Kind)\n\t\t}\n\t\tif item.Create == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif item.Create.Issue == nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: apply batch item %d requires an issue\", issueops.ErrValidation, i)\n\t\t}\n\t\tif len(item.Create.Issue.Comments) > 0 || len(item.Create.Issue.Dependencies) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"%w: apply batch item %d must not carry comments or dependencies on the issue; edges are their own items\",\n\t\t\t\tissueops.ErrValidation, i)\n\t\t}\n\t\tif item.Create.Key == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif prior, dup := keyIndex[item.Create.Key]; dup {\n\t\t\treturn nil, fmt.Errorf(\"%w: apply batch item %d reuses key %q, already declared by item %d\",\n\t\t\t\tissueops.ErrValidation, i, item.Create.Key, prior)\n\t\t}\n\t\tkeyIndex[item.Create.Key] = i\n\t}\n\treturn keyIndex, nil\n}\n\n// planApplyBatchItem validates one item's refs, guards and edge metadata, and","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/batch_apply.go#L129-L165","documentation":"A create-kind batch item must embed an Issue payload; this error fires when item.Create is non-nil but item.Create.Issue is nil. The planner needs the issue row to know what to insert, and there is nothing to plan without it. Wraps issueops.ErrValidation.","triggerScenarios":"PlanApplyBatch with an item where Kind is ItemCreate and Create != nil, but Create.Issue was never assigned (zero-value CreateItem or Issue field forgotten).","commonSituations":"Constructing CreateItem{Key: \"x\"} and populating the issue later in code that errored or was skipped; unmarshaling partial JSON where the issue object was absent.","solutions":["Assign a complete CreateItem.Issue before calling PlanApplyBatch","Check the item construction path for a branch that skips setting Issue","Assert non-nil Issue in the code that builds the batch"],"exampleFix":"// before\nitem := issueops.ApplyItem{Kind: issueops.ItemCreate, Create: &issueops.CreateItem{Key: \"bd-1\"}}\n// after\nitem := issueops.ApplyItem{Kind: issueops.ItemCreate, Create: &issueops.CreateItem{Key: \"bd-1\", Issue: &types.Issue{Title: \"Fix login\", Status: \"open\"}}}","handlingStrategy":"validation","validationCode":"for i, it := range items {\n  if it.Kind == issueops.ItemCreate && it.Create != nil && it.Create.Issue == nil {\n    return fmt.Errorf(\"create item %d has no Issue\", i)\n  }\n}","typeGuard":"func hasIssue(it *issueops.CreateItem) bool { return it != nil && it.Issue != nil }","tryCatchPattern":"if err := store.PlanApplyBatch(plan); err != nil {\n  if errors.Is(err, issueops.ErrValidation) && strings.Contains(err.Error(), \"requires an issue\") {\n    // rebuild the plan with the Issue populated\n  }\n  return err\n}","preventionTips":["Always construct CreateItem with both Key and Issue in one helper","Check for skipped assignments when Issue is built conditionally","Validate payload completeness at the batch-builder boundary"],"tags":["validation","batch-apply","nil-issue"],"backgroundTag":"batch-item-missing-payload","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}