{"record":{"id":"850345abeaa6d187","repo":"gastownhall/beads","slug":"search-union-with-counts-hydrate-wisps-w","errorCode":null,"errorMessage":"search union with counts (hydrate wisps): %w","messagePattern":"search union with counts \\(hydrate wisps\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/issue_search_counts.go","lineNumber":107,"sourceCode":"\t\treturn domain.SearchCountsPage{}, fmt.Errorf(\"search union with counts: %w\", err)\n\t}\n\tpage, err := scanIDSrcPage(rows)\n\tif err != nil {\n\t\treturn domain.SearchCountsPage{}, fmt.Errorf(\"search union with counts: %w\", err)\n\t}\n\tpage.sortGoSide(filter.SortBy, filter.SortDesc)\n\thasMore, err := page.finishWindow(window)\n\tif err != nil {\n\t\treturn domain.SearchCountsPage{}, err\n\t}\n\n\tissuesByID, err := r.fetchCountsByIDs(ctx, page.issueIDs, issuesFilterTables, wispDepsExist, hydrationFor(filter))\n\tif err != nil {\n\t\treturn domain.SearchCountsPage{}, fmt.Errorf(\"search union with counts (hydrate issues): %w\", err)\n\t}\n\twispsByID, err := r.fetchCountsByIDs(ctx, page.wispIDs, wispsFilterTables, true, hydrationFor(filter))\n\tif err != nil && !missingOptionalWispTable(err) {\n\t\treturn domain.SearchCountsPage{}, fmt.Errorf(\"search union with counts (hydrate wisps): %w\", err)\n\t}\n\n\tout := reassembleBySrc(page.ordered, issuesByID, wispsByID)\n\treturn domain.SearchCountsPage{Items: out, HasMore: hasMore}, nil\n}\n\n// hydrationFor reads the hydration opt-outs off a search filter, matching the\n// store-backed path's helper of the same name (internal/storage/issueops).\n// Both bodies must read the same fields off the same filter or a caller that\n// set one would get different columns from the two backends.\nfunc hydrationFor(filter types.IssueFilter) sqlbuild.CountsHydration {\n\treturn sqlbuild.CountsHydration{SkipLabels: filter.SkipLabels, SkipCounts: filter.SkipCounts, Lite: filter.Lite}\n}\n\n// readyHydrationFor is the WORK-filter twin, matching\n// issueops.readyHydrationFor. See it for why a ready filter carries Lite and\n// neither of the other two.\nfunc readyHydrationFor(filter types.WorkFilter) sqlbuild.CountsHydration {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/issue_search_counts.go#L89-L125","documentation":"Same as the issues hydration wrapper but for wisp IDs. Unlike issues, a missing optional wisp table is tolerated (missingOptionalWispTable); only real failures other than 'table missing' are wrapped and returned. Indicates the wisp-side counts mega-query failed for a non-missing-table reason.","triggerScenarios":"fetchCountsByIDs on page.wispIDs fails with an error that is not the tolerated missing-wisp-table sentinel — e.g. engine error, cancellation, or malformed counts query for wisp tables.","commonSituations":"wisp_dependencies exists but another wisp-related table is missing/incompatible, hydration of a large wisp page times out, or connection drop mid-hydration.","solutions":["Read the inner wrapped error; if it IS a missing-table error this path would have succeeded, so look for a different cause","Run migrations/doctor to reconcile wisp schema","Use filter.Ephemeral=true to query wisps alone, or SkipWisps to avoid the leg","Retry transient network/cancellation failures"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"if !wispTablesExist(ctx, db) {\n    filter.SkipWisps = true\n}","typeGuard":null,"tryCatchPattern":"page, err := store.SearchWithCounts(ctx, q, filter)\nif err != nil && strings.Contains(err.Error(), \"hydrate wisps\") {\n    filter.SkipWisps = true // tolerate wisp hydration failure\n    page, err = store.SearchWithCounts(ctx, q, filter)\n}","preventionTips":["Ensure wisp schema is complete whenever wisp_dependencies exists","Treat missing optional wisp tables as non-fatal (library already does)","Test searches in DBs both with and without wisps tables","Keep wisp pages small to limit hydration load"],"tags":["sql","hydration","wisps"],"backgroundTag":"sql-query-execution-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}