gastownhall/beads · error

db: CommentSQLRepository.InsertRecord: issue %s not found

Error message

db: CommentSQLRepository.InsertRecord: issue %s not found

What it means

The existence probe returned exists=false: the parent issue ID is valid non-empty text but no row with that id exists in the selected issue table (issues or issues_wisps). The repository refuses to create a comment for a nonexistent issue, keeping referential integrity.

Source

Thrown at internal/storage/domain/db/comment.go:145

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()
	}
	createdAtText := issueops.FormatAuxTime(copy.CreatedAt)
	commentTable := pickCommentTable(opts.UseWispsTable)
	if copy.ID == "" {
		id, _, err := issueops.InsertDerivedComment(ctx, r.runner, commentTable, copy.IssueID, copy.Author, copy.Text, createdAtText)
		if err != nil {
			return nil, fmt.Errorf("db: CommentSQLRepository.InsertRecord: %w", err)
		}
		copy.ID = id
	} else {
		//nolint:gosec // G201: commentTable is one of two hardcoded constants
		if _, err := r.runner.ExecContext(ctx, fmt.Sprintf(`

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the issue ID exists (bd show <id> or SELECT) in the same database and table selection.
  2. Correct the IssueID (typo/prefix) or create the issue first.
  3. Make opts.UseWispsTable consistent with how the issue was created (wisp vs regular issue).
  4. Skip/requeue comments whose parent issue was deleted instead of failing the whole import.

Example fix

// before
repo.InsertRecord(ctx, &types.Comment{IssueID: "bd-999", Text: "x"}, opts) // bd-999 absent
// after
if issue, err := issueRepo.Get(ctx, "bd-999"); err == nil {
    repo.InsertRecord(ctx, &types.Comment{IssueID: issue.ID, Text: "x"}, opts)
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure the parent issue exists before inserting the comment
var exists bool
_ = runner.QueryRowContext(ctx,
    "SELECT EXISTS(SELECT 1 FROM issues WHERE id = ?)", issueID).Scan(&exists)
if !exists {
    return fmt.Errorf("refusing to comment on unknown issue %s", issueID)
}

Type guard

func issueExists(ctx context.Context, r domain.IssueSQLRepository, id string) bool {
    _, err := r.Get(ctx, id)
    return err == nil
}

Try / catch

if _, err := repo.InsertRecord(ctx, c, opts); err != nil {
    if strings.Contains(err.Error(), "not found") && strings.Contains(err.Error(), c.IssueID) {
        // create or look up the correct issue first; skip orphan comments in imports
    }
}

Prevention

When it happens

Trigger: InsertRecord(ctx, &types.Comment{IssueID: "bd-123", ...}, opts) where bd-123 is not in the issue table — wrong prefix, typo'd ID, ID from a different database, or UseWispsTable set inconsistently with where the issue actually lives (issue created in wisps table but comment inserted with the wrong table selection, or vice versa).

Common situations: Copy-pasting IDs between repos/databases, importing comments before importing the issues, stale IDs after a DB reset, or a mismatch between the table chosen via opts.UseWispsTable and where the issue was created.

Related errors


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