gastownhall/beads · error
create: issue must not be nil
Error message
create: issue must not be nil
What it means
createParams rejects a CreateRequest whose Issue field is nil before doing any storage work. The request must carry the issue payload to create; a nil pointer would otherwise panic during cloning and parameter building. It is a validationError, so callers can distinguish bad input from storage failures.
Source
Thrown at internal/storage/uow/issue_operations.go:121
if useWisp {
created, err = uw.IssueUseCase().CreateWisp(ctx, params, attempt.Actor)
} else {
created, err = uw.IssueUseCase().CreateIssue(ctx, params, attempt.Actor)
}
if err != nil {
return publicops.CreateResult{}, "", storageissueops.ClassifyPublicCreateError(err)
}
issue, err := hydrateIssueOperation(ctx, uw, created.Issue, true, false)
if err != nil {
return publicops.CreateResult{}, "", err
}
return publicops.CreateResult{Issue: issue}, "create issue", nil
})
}
func createParams(request publicops.CreateRequest) (domain.CreateIssueParams, bool, error) {
if request.Issue == nil {
return domain.CreateIssueParams{}, false, fmt.Errorf("create: issue must not be nil")
}
issue := storageissueops.CloneCreateRequest(publicops.CreateRequest{Issue: request.Issue}).Issue
params := domain.CreateIssueParams{
Issue: issue,
ExplicitID: issue.ID,
ParentID: request.ParentID,
Labels: append([]string(nil), issue.Labels...),
InheritLabelsFromParent: request.InheritLabelsFromParent,
ForcePrefix: request.ForceIDPrefix,
CreateOnly: true,
}
for _, dependency := range request.Dependencies {
params.Dependencies = append(params.Dependencies, domain.DependencySpec{
Type: dependency.Type,
TargetID: dependency.TargetID,
SwapDirection: dependency.Reverse,
Metadata: dependency.Metadata,
ThreadID: dependency.ThreadID,View on GitHub (pinned to 71377f2769)
Solutions
- Always populate CreateRequest.Issue with a non-nil *types.Issue.
- Check the struct is fully initialized after deserialization before dispatching.
- Add a nil check on Issue at the construction site if it can come from external input.
Example fix
// before
req := publicops.CreateRequest{} // Issue nil
// after
req := publicops.CreateRequest{Issue: &types.Issue{ID: id, Title: title, Status: "open"}} Defensive patterns
Strategy: validation
Validate before calling
if req.Issue == nil { return errors.New("create: issue is required") } Type guard
func validCreateRequest(r publicops.CreateRequest) bool { return r.Issue != nil } Try / catch
if err != nil {
// validationError family: fix the request, do not retry
return fmt.Errorf("bad create request: %w", err)
} Prevention
- Never dispatch a zero-value CreateRequest.
- Validate deserialized payloads for null issue objects.
- Add a builder that guarantees a non-nil Issue.
When it happens
Trigger: Calling Create (or batch-create paths applyCreate/createBatchItem) with publicops.CreateRequest{Issue: nil}.
Common situations: Zero-value CreateRequest passed by mistake; a builder that failed earlier and left Issue nil; JSON deserialization that produced a null issue object.
Related errors
- config storage-class.%s: %w
- nil entry
- issue must not be nil
- add dep: dep must not be nil
- ensure issue ID available: ID is empty
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0ab0ac05ad0c0ce7.
Report an issue: GitHub.