gastownhall/beads · error
db: CommentSQLRepository.InsertRecord: issueID must not be e
Error message
db: CommentSQLRepository.InsertRecord: issueID must not be empty
What it means
After dereferencing the comment, InsertRecord requires IssueID to be non-empty because every comment row is keyed to an issue (issues/issues_wisps table). An empty IssueID would never match the foreign issue, so the repository rejects it up front with this guard.
Source
Thrown at internal/storage/domain/db/comment.go:134
func (r *commentSQLRepositoryImpl) Insert(ctx context.Context, issueID, author, text string, opts domain.CommentOpts) (*types.Comment, error) {
// Live add: advance past the issue's newest comment so a burst inside one
// second still reads back in write order (issueops.NextLiveCommentTime).
// InsertRecord honors a supplied CreatedAt verbatim, which is what keeps
// imported comments on their original timestamps.
stamp, err := issueops.NextLiveCommentTime(ctx, r.runner, pickCommentTable(opts.UseWispsTable), issueID, time.Now())
if err != nil {
return nil, fmt.Errorf("db: CommentSQLRepository.Insert: %w", err)
}
return r.InsertRecord(ctx, &types.Comment{IssueID: issueID, Author: author, Text: text, CreatedAt: stamp}, opts)
}
func (r *commentSQLRepositoryImpl) InsertRecord(ctx context.Context, comment *types.Comment, opts domain.CommentOpts) (*types.Comment, error) {
if comment == nil {
return nil, fmt.Errorf("db: CommentSQLRepository.InsertRecord: comment must not be nil")
}
copy := *comment
if copy.IssueID == "" {
return nil, fmt.Errorf("db: CommentSQLRepository.InsertRecord: issueID must not be empty")
}
issueTable := pickIssueTable(opts.UseWispsTable)
var exists bool
//nolint:gosec // G201: issueTable is one of two hardcoded constants
if err := r.runner.QueryRowContext(ctx,
fmt.Sprintf("SELECT EXISTS(SELECT 1 FROM %s WHERE id = ?)", issueTable), copy.IssueID).Scan(&exists); err != nil {
return nil, fmt.Errorf("db: CommentSQLRepository.InsertRecord: check issue existence: %w", err)
}
if !exists {
return nil, fmt.Errorf("db: CommentSQLRepository.InsertRecord: issue %s not found", copy.IssueID)
}
if copy.CreatedAt.IsZero() {
copy.CreatedAt = time.Now().UTC()
} else {
copy.CreatedAt = copy.CreatedAt.UTC()
}View on GitHub (pinned to 71377f2769)
Solutions
- Set comment.IssueID to a valid issue ID before calling InsertRecord.
- Resolve the issue (e.g. via a lookup by title/prefix) and use its ID.
- Skip insertion when the parent ID is empty and log/report the orphan comment instead of calling the repository.
Example fix
// before
repo.InsertRecord(ctx, &types.Comment{Author: "me", Text: "hi"}, opts)
// after
repo.InsertRecord(ctx, &types.Comment{IssueID: issue.ID, Author: "me", Text: "hi"}, opts) Defensive patterns
Strategy: validation
Validate before calling
func validateComment(c *types.Comment) error {
if c == nil || c.IssueID == "" {
return fmt.Errorf("comment requires a non-empty IssueID")
}
return nil
} Type guard
func hasIssueID(c *types.Comment) bool { return c != nil && c.IssueID != "" } Try / catch
if _, err := repo.InsertRecord(ctx, c, opts); err != nil {
if strings.Contains(err.Error(), "issueID must not be empty") {
// resolve the parent issue and populate IssueID, then retry
}
} Prevention
- Always populate IssueID when constructing a types.Comment.
- Add a NewComment(issueID, author, text) constructor that asserts a non-empty issue ID.
- Cover the empty-ID guard in unit tests.
When it happens
Trigger: Calling InsertRecord with a types.Comment whose IssueID field was never set, calling it with comment.IssueID == "" after a failed lookup, or constructing the struct with named fields and omitting IssueID.
Common situations: Import scripts that forgot to map the parent issue key, code paths where the issue ID comes from a config/env value that is empty, or tests constructing partial fixtures.
Related errors
- db: CommentSQLRepository.InsertRecord: comment must not be n
- no store is open for this workspace
- not found
- no absolute native user directory is available
- ExternalDoltConfig: set either Socket OR (Host, Port), not b
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/55ffa956b056eccf.
Report an issue: GitHub.