{"record":{"id":"be2a1d506da7fd8a","repo":"gastownhall/beads","slug":"failed-to-scan-comment-w","errorCode":null,"errorMessage":"failed to scan comment: %w","messagePattern":"failed to scan comment: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/events.go","lineNumber":185,"sourceCode":"// GetCommentCounts returns the number of comments for each issue in a single batch query.\n// Delegates to issueops.GetCommentCountsInTx for shared query logic.\nfunc (s *DoltStore) GetCommentCounts(ctx context.Context, issueIDs []string) (map[string]int, error) {\n\tvar result map[string]int\n\terr := s.withReadTx(ctx, func(tx *sql.Tx) error {\n\t\tvar err error\n\t\tresult, err = issueops.GetCommentCountsInTx(ctx, tx, issueIDs)\n\t\treturn err\n\t})\n\treturn result, err\n}\n\n// scanComments scans comment rows into a slice.\nfunc scanComments(rows *sql.Rows) ([]*types.Comment, error) {\n\tvar comments []*types.Comment\n\tfor rows.Next() {\n\t\tvar c types.Comment\n\t\tif err := rows.Scan(&c.ID, &c.IssueID, &c.Author, &c.Text, &c.CreatedAt); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to scan comment: %w\", err)\n\t\t}\n\t\tcomments = append(comments, &c)\n\t}\n\treturn comments, rows.Err()\n}\n","sourceCodeStart":167,"sourceCodeEnd":191,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/events.go#L167-L191","documentation":"scanComments fails when a comment row cannot be scanned into types.Comment — the result set's columns don't match the scan destinations (ID, IssueID, Author, Text, CreatedAt). Typically caused by NULLs in non-nullable fields or a column type/count mismatch after schema changes. The raw sql error is wrapped for inspection.","triggerScenarios":"A comment row has NULL author, text, or created_at (e.g. inserted manually via dolt sql); the comments table was altered so column order/types differ; a schema migration left mixed-format rows.","commonSituations":"Hand-editing the database with `dolt sql` and omitting required fields; upgrading bd across versions where the Comment struct gained fields the old schema can't satisfy; restoring a partial backup missing some columns.","solutions":["Find the offending row(s) via SQL (`SELECT * FROM comments WHERE author IS NULL OR text IS NULL OR created_at IS NULL`) and fix or delete them.","If you altered the comments table, restore the expected schema (column names, order, types, NOT NULL constraints).","Run any pending migrations (`bd doctor` / migrate) so the schema matches the code's expectations.","As a last resort, export good data, recreate the table with the canonical schema, and re-import."],"exampleFix":"// before: manual insert leaving NULLs\nINSERT INTO comments (id, issue_id, text) VALUES ('c1', 'bd-1', 'hi');\n// after: supply all non-nullable columns\nINSERT INTO comments (id, issue_id, author, text, created_at)\nVALUES ('c1', 'bd-1', 'alice', 'hi', NOW());","handlingStrategy":"validation","validationCode":"// SQL: detect rows that will fail the scan before reading via bd\nSELECT id FROM comments\nWHERE author IS NULL OR text IS NULL OR created_at IS NULL OR issue_id IS NULL;","typeGuard":"func IsCommentScanError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"failed to scan comment\")\n}","tryCatchPattern":"comments, err := store.GetIssueComments(ctx, issueID)\nif err != nil && strings.Contains(err.Error(), \"failed to scan comment\") {\n\treturn fmt.Errorf(\"corrupt comment row; fix NULLs in comments table: %w\", err)\n}","preventionTips":["Never insert comment rows manually without all required columns.","Enforce NOT NULL constraints in the comments schema and rely on them.","Validate schema after restores/backups before normal use.","Use nullable Go scan types if a column is legitimately optional."],"tags":["database","dolt","scan","schema","comments"],"backgroundTag":"row-scan-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}