{"record":{"id":"9de215ea146712ec","repo":"gastownhall/beads","slug":"determining-blocked-wisps-for-age-gc-w","errorCode":null,"errorMessage":"determining blocked wisps for age GC: %w","messagePattern":"determining blocked wisps for age GC: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/wisp.go","lineNumber":838,"sourceCode":"\t}\n\treturn nil\n}\n\nfunc findAbandonedWisps(ctx context.Context, r molReader, cleanAll bool, ageThreshold time.Duration, excludeTypes []types.IssueType) ([]*types.Issue, error) {\n\tephemeralFlag := true\n\tfilter := types.IssueFilter{\n\t\tEphemeral:    &ephemeralFlag,\n\t\tExcludeTypes: excludeTypes,\n\t\tLimit:        5000,\n\t}\n\tissues, err := r.SearchIssues(ctx, \"\", filter)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tblocked, err := r.GetBlockedIssues(ctx, types.WorkFilter{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"determining blocked wisps for age GC: %w\", err)\n\t}\n\tblockedSet := make(map[string]bool, len(blocked))\n\tfor _, b := range blocked {\n\t\tblockedSet[b.ID] = true\n\t}\n\n\tprotectedStatuses, err := protectedWispStatuses(ctx, r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tnow := time.Now()\n\tvar abandoned []*types.Issue\n\tfor _, issue := range issues {\n\t\tif r.IsInfraTypeCtx(ctx, issue.IssueType) {\n\t\t\tcontinue\n\t\t}\n\t\tif issue.Status == types.StatusClosed && !cleanAll {","sourceCodeStart":820,"sourceCodeEnd":856,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/wisp.go#L820-L856","documentation":"Wisp age GC must exclude blocked wisps from abandonment detection. If querying the blocked-issue set via r.GetBlockedIssues fails, findAbandonedWisps aborts with this wrapped error instead of proceeding with an incomplete picture that could GC live, blocked wisps.","triggerScenarios":"runWispGC or runWispGCProxiedServer → findAbandonedWisps → r.GetBlockedIssues(ctx, types.WorkFilter{}) returns a driver/store error.","commonSituations":"Database unavailable or locked during scheduled GC; large dependency graphs timing out the blocked-issues query; proxied-server storage errors.","solutions":["Check database connectivity and retry `bd wisp gc`","Investigate the wrapped inner error for the storage/driver root cause","Run GC when the database is not under heavy write load"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := ctx.Err(); err != nil { return err }\nif _, err := r.GetBlockedIssues(ctx, types.WorkFilter{}); err != nil {\n    return fmt.Errorf(\"cannot determine blocked set; aborting GC: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := runWispGC(ctx); err != nil {\n    if strings.Contains(err.Error(), \"determining blocked wisps for age GC\") {\n        // back off and retry; do not GC with an incomplete blocked set\n    }\n}","preventionTips":["Schedule GC during low database load","Retry the blocked-issues query with backoff before aborting","Never proceed with abandonment detection when the blocked set is unavailable"],"tags":["gc","storage","dependencies"],"backgroundTag":"storage-read-failure","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}