{"record":{"id":"981588441ca038d0","repo":"gastownhall/beads","slug":"iterate-wisp-issues-by-label-w","errorCode":null,"errorMessage":"iterate wisp issues by label: %w","messagePattern":"iterate wisp issues by label: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/bulk_ops.go","lineNumber":86,"sourceCode":"\tif err := rows.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"iterate issues by label: %w\", err)\n\t}\n\n\twispRows, err := tx.QueryContext(ctx, `SELECT issue_id FROM wisp_labels WHERE label = ?`, label)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get wisp issues by label: %w\", err)\n\t}\n\tdefer wispRows.Close()\n\n\tfor wispRows.Next() {\n\t\tvar id string\n\t\tif err := wispRows.Scan(&id); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"scan wisp issue id: %w\", err)\n\t\t}\n\t\tids = append(ids, id)\n\t}\n\tif err := wispRows.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"iterate wisp issues by label: %w\", err)\n\t}\n\n\treturn ids, nil\n}\n\n// DeleteConfigInTx removes a configuration value.\nfunc DeleteConfigInTx(ctx context.Context, tx *sql.Tx, key string) error {\n\t_, err := tx.ExecContext(ctx, \"DELETE FROM config WHERE `key` = ?\", key)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"delete config %s: %w\", key, err)\n\t}\n\treturn nil\n}\n\n// GetCommentsForIssuesInTx retrieves comments for multiple issues, partitioning\n// between comments and wisp_comments tables.\n//\n//nolint:gosec // G201: table is hardcoded","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/bulk_ops.go#L68-L104","documentation":"GetIssuesByLabelInTx wraps a row-iteration error from the wisp-issues label query with this message after rows.Scan succeeded but wispRows.Err() reported a driver/SQL failure mid-iteration. It means the ID list is incomplete because the underlying query failed while advancing the result set.","triggerScenarios":"The rows cursor over wisp issues by label hits a database error between Scan calls — connection drop, context cancellation/timeouts, Dolt server restart, or driver-level failure during iteration.","commonSituations":"Long-running bulk operations on flaky connections; CLI context timeout expiring mid-query; embedded Dolt process killed during a large label scan; network interruption in remote/server mode.","solutions":["Retry GetIssuesByLabelInTx (the read is idempotent) once the connection/context is healthy.","Inspect the wrapped driver error for connection/cancellation causes; extend the context deadline if it timed out.","Check database server health/logs and connectivity before rerunning."],"exampleFix":"// before\nids, err := issueops.GetIssuesByLabelInTx(ctx, tx, label) // err: iterate wisp issues by label: context deadline exceeded\n// after\nctx, cancel := context.WithTimeout(ctx, 60*time.Second)\ndefer cancel()\nids, err := issueops.GetIssuesByLabelInTx(ctx, tx, label)\nif err != nil {\n    return retryRead(ctx, label) // bounded retry\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isIterationFailure(err error) bool { return err != nil && strings.Contains(err.Error(), \"iterate wisp issues by label\") }","tryCatchPattern":"ids, err := issueops.GetIssuesByLabelInTx(ctx, tx, label)\nif err != nil {\n    if ctx.Err() != nil || isTransientDB(err) {\n        return retryWithBackoff(3, func() error { _, e := issueops.GetIssuesByLabelInTx(ctx, tx, label); return e })\n    }\n    return err\n}","preventionTips":["Use a context deadline generous enough for large label scans.","Retry read-only queries on transient driver/connection errors.","Monitor database server health for embedded/remote Dolt instances.","Treat the returned ID list as incomplete after this error — always re-query."],"tags":["go","database","query","iteration"],"backgroundTag":"row-iteration-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}