{"record":{"id":"392125c7c07be0e9","repo":"gastownhall/beads","slug":"db-commentsqlrepository-insertrecord-w","errorCode":null,"errorMessage":"db: CommentSQLRepository.InsertRecord: %w","messagePattern":"db: CommentSQLRepository\\.InsertRecord: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/comment.go","lineNumber":158,"sourceCode":"\tif err := r.runner.QueryRowContext(ctx,\n\t\tfmt.Sprintf(\"SELECT EXISTS(SELECT 1 FROM %s WHERE id = ?)\", issueTable), copy.IssueID).Scan(&exists); err != nil {\n\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.InsertRecord: check issue existence: %w\", err)\n\t}\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.InsertRecord: issue %s not found\", copy.IssueID)\n\t}\n\n\tif copy.CreatedAt.IsZero() {\n\t\tcopy.CreatedAt = time.Now().UTC()\n\t} else {\n\t\tcopy.CreatedAt = copy.CreatedAt.UTC()\n\t}\n\tcreatedAtText := issueops.FormatAuxTime(copy.CreatedAt)\n\tcommentTable := pickCommentTable(opts.UseWispsTable)\n\tif copy.ID == \"\" {\n\t\tid, _, err := issueops.InsertDerivedComment(ctx, r.runner, commentTable, copy.IssueID, copy.Author, copy.Text, createdAtText)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.InsertRecord: %w\", err)\n\t\t}\n\t\tcopy.ID = id\n\t} else {\n\t\t//nolint:gosec // G201: commentTable is one of two hardcoded constants\n\t\tif _, err := r.runner.ExecContext(ctx, fmt.Sprintf(`\n\t\t\tINSERT INTO %s (id, issue_id, author, text, created_at)\n\t\t\tVALUES (?, ?, ?, ?, ?)\n\t\t`, commentTable), copy.ID, copy.IssueID, copy.Author, copy.Text, createdAtText); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.InsertRecord: %w\", err)\n\t\t}\n\t}\n\tcreatedAt, err := issueops.ParseAuxTime(createdAtText)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.InsertRecord: %w\", err)\n\t}\n\tcopy.CreatedAt = createdAt\n\n\tif err := issueops.RecordCommentEventInTx(ctx, r.runner, copy.IssueID, &issueops.EventComment{","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/comment.go#L140-L176","documentation":"When the comment has no pre-assigned ID, InsertRecord delegates to issueops.InsertDerivedComment, which generates an ID and performs the INSERT. Any error from that helper (ID-generation conflict, insert failure, table missing, connection error) is wrapped verbatim with this prefix. The call site adds no extra context, so the underlying driver error text is the real diagnostic.","triggerScenarios":"issueops.InsertDerivedComment fails: ID collision/uniqueness constraint on the comment table, issues_wisps/issues comment table missing, locked database, context cancellation, or disk/connection failure during INSERT.","commonSituations":"Concurrent inserts racing on derived IDs, corrupted or locked Dolt/SQLite file, importing into a database with an outdated schema lacking the comment table.","solutions":["Read the wrapped driver error after the prefix to identify the concrete failure.","Retry on transient lock/connection errors; investigate persistent uniqueness collisions.","Run schema migration so pickCommentTable(opts.UseWispsTable) resolves to an existing table.","Check for concurrent writers hammering the same database."],"exampleFix":"// before\n// insert fails with ambiguous wrapped error; cause unknown\nrepo.InsertRecord(ctx, c, opts)\n// after\nif _, err := repo.InsertRecord(ctx, c, opts); err != nil {\n    log.Errorf(\"insert comment: %v\", errors.Unwrap(err)) // inspect real cause\n}","handlingStrategy":"retry","validationCode":"// pre-check schema so derived inserts hit an existing table\nvar name string\n_ = runner.QueryRowContext(ctx,\n    \"SELECT table_name FROM information_schema.tables WHERE table_name IN ('comments','comments_wisps')\").Scan(&name)","typeGuard":"null","tryCatchPattern":"if _, err := repo.InsertRecord(ctx, c, opts); err != nil {\n    if strings.Contains(err.Error(), \"db: CommentSQLRepository.InsertRecord:\") {\n        cause := errors.Unwrap(err)\n        if isTransient(cause) { // lock/connection\n            return retryWithBackoff(ctx, func() error { _, err := repo.InsertRecord(ctx, c, opts); return err })\n        }\n        return fmt.Errorf(\"derived comment insert failed: %w\", cause)\n    }\n}","preventionTips":["Keep the schema migrated so comment tables exist for both regular and wisp modes.","Avoid many concurrent writers contending on the same database file.","Inspect errors.Unwrap(err) to see the real driver failure instead of guessing.","Add unit tests inserting via the derived-ID path against a temp database."],"tags":["go","sql","insert","id-generation"],"backgroundTag":"sql-insert-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}