{"record":{"id":"867a99c8f83903ef","repo":"gastownhall/beads","slug":"scanning-open-wisps-for-references-w","errorCode":null,"errorMessage":"scanning open wisps for references: %w","messagePattern":"scanning open wisps for references: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/uow/sweeper.go","lineNumber":167,"sourceCode":"\t// BOTH PLANES, and this is not an optimization detail. The not-done set\n\t// comes from SearchIssues, which merges the durable and wisp planes, so it\n\t// contains wisps — and their comments live in wisp_comments, which\n\t// GetCommentsForIssues does not read. Scanning only the durable table left\n\t// a closed bead cited solely by a comment on an open WISP unprotected, so\n\t// `bd prune` deleted it on this route and kept it on the other. The\n\t// contract says an implementation that cannot read the full set must fail\n\t// the sweep rather than under-scan it.\n\t//\n\t// The full id list goes to both reads rather than being partitioned by a\n\t// plane flag: an id lives in exactly one plane, so at most one side answers\n\t// for it, and a mis-partition here would silently under-scan again.\n\tcomments, err := uw.CommentUseCase().GetCommentsForIssues(ctx, notDoneIDs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"scanning open beads for references: %w\", err)\n\t}\n\twispComments, err := uw.CommentUseCase().GetCommentsForWisps(ctx, notDoneIDs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"scanning open wisps for references: %w\", err)\n\t}\n\tfor id, cs := range wispComments {\n\t\tcomments[id] = append(comments[id], cs...)\n\t}\n\n\treferenced := make(map[string]bool)\n\tfor _, issue := range notDone {\n\t\tif issue == nil {\n\t\t\tcontinue\n\t\t}\n\t\tmatcher.FindAll(issue.Description, referenced)\n\t\tmatcher.FindAll(issue.Notes, referenced)\n\t\tfor _, c := range comments[issue.ID] {\n\t\t\tmatcher.FindAll(c.Text, referenced)\n\t\t}\n\t}\n\treturn referenced, nil\n}","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/uow/sweeper.go#L149-L185","documentation":"This wraps a failure from CommentUseCase().GetCommentsForWisps while reading comments for open wisps (the ephemeral plane) during the sweep reference scan. Wisps' comments live in a separate wisp_comments table; a failure there means the scan cannot prove candidates unreferenced, so the sweep aborts rather than under-scan and delete a bead cited only by a wisp comment.","triggerScenarios":"bd prune/sweep when the batched wisp_comments query for the not-done ID list fails — SQL error on the wisp plane, connection loss, or timeout on a large not-done set.","commonSituations":"Large numbers of open wisps making the batch query slow; Dolt server restart mid-sweep; schema drift in wisp_comments between beads versions.","solutions":["Inspect the wrapped cause and fix the underlying wisp-comments query failure","Retry the sweep once the database is reachable","Raise query timeouts / batch size limits for very large wisp sets","Run database repair/consistency tooling if corruption is reported"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Ensure the wisp comments table is readable before sweeping\nrows, err := db.QueryContext(ctx, \"SELECT 1 FROM wisp_comments LIMIT 1\")\nif err != nil {\n    return fmt.Errorf(\"wisp_comments not readable, skip sweep: %w\", err)\n}\nrows.Close()","typeGuard":null,"tryCatchPattern":"result, err := sweeper.Sweep(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"scanning open wisps for references\") {\n    // wisp-plane comment read failed; restore DB health and retry\n    return retrySweepWithBackoff(ctx, req)\n}","preventionTips":["Compact/expire stale wisps regularly to keep the wisp set small","Keep the Dolt connection alive for the full sweep duration","Apply schema migrations after beads upgrades before sweeping","Monitor for corruption and repair early"],"tags":["storage","wisps","sweep"],"backgroundTag":"database-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}