{"record":{"id":"3328607f4a47681e","repo":"gastownhall/beads","slug":"descendants-issues-filter-w","errorCode":null,"errorMessage":"descendants: issues filter: %w","messagePattern":"descendants: issues filter: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/issue_descendants.go","lineNumber":46,"sourceCode":"\t\treturn predBundle{}\n\t}\n\treturn predBundle{\n\t\tmatchesCTE: fmt.Sprintf(\"%s AS (SELECT id FROM %s WHERE %s)\",\n\t\t\tcteName, table, strings.Join(clauses, \" AND \")),\n\t\tsnippet: fmt.Sprintf(\" AND %s.id IN (SELECT id FROM %s)\", alias, cteName),\n\t\targs:    args,\n\t}\n}\n\nfunc (r *issueSQLRepositoryImpl) GetDescendants(ctx context.Context, rootID string, filter types.IssueFilter) ([]*types.Issue, error) {\n\tlevelFilter := filter\n\tlevelFilter.ParentID = nil\n\tlevelFilter.Limit = 0\n\tlevelFilter.Offset = 0\n\n\tissueWhereClauses, issueArgs, err := buildIssueFilterClauses(\"\", levelFilter, issuesFilterTables)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"descendants: issues filter: %w\", err)\n\t}\n\n\twispDepsExist, err := r.optionalTableExists(ctx, \"wisp_dependencies\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"descendants: wisp_dependencies probe: %w\", err)\n\t}\n\twalkWisps := wispDepsExist && !filter.SkipWisps\n\tif walkWisps {\n\t\tempty, probeErr := r.wispsTableEmptyOrMissing(ctx)\n\t\tif probeErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"descendants: wisps table probe: %w\", probeErr)\n\t\t}\n\t\twalkWisps = !empty\n\t}\n\n\tvar wispWhereClauses []string\n\tvar wispArgs []any\n\tif walkWisps {","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/issue_descendants.go#L28-L64","documentation":"Wraps a failure from buildIssueFilterClauses while constructing the WHERE clauses for the issues side of a descendants walk in GetDescendants. Clause building validates filter fields; an unsupported filter combination or invalid value fails here before any SQL runs. The resulting error prevents the recursive descendant query from being built.","triggerScenarios":"Calling GetDescendants with an IssueFilter that BuildIssueFilterClauses cannot translate: unsupported field, invalid status/priority values, or a filter combination the shared SQL builder rejects. Level/parent/limit fields are deliberately zeroed first, so those cannot be the cause — the caller's remaining filter fields are.","commonSituations":"Passing a filter populated for a different API (fields unsupported in descendants context), typo'd or out-of-range status/priority values, or an upgraded library where new filter fields are not yet handled by the builder.","solutions":["Read the wrapped cause — the builder names the rejected filter field/value.","Strip or simplify the IssueFilter passed to GetDescendants; filter results in Go instead of SQL.","Verify status/priority values against types constants (not raw strings).","Check for version mismatch between your filter struct fields and the installed storage library."],"exampleFix":"// before\nfilter.Status = []string{\"opn\"} // typo'd status\ndeps, err := repo.GetDescendants(ctx, epicID, filter)\n// after\nfilter.Status = []string{types.StatusOpen.String()}\ndeps, err := repo.GetDescendants(ctx, epicID, filter)","handlingStrategy":"validation","validationCode":"// validate the filter yourself before GetDescendants\nfor _, s := range filter.Status {\n    if !types.IsValidStatus(s) { return fmt.Errorf(\"invalid status %q\", s) }\n}","typeGuard":null,"tryCatchPattern":"deps, err := repo.GetDescendants(ctx, id, filter)\nif err != nil {\n    if strings.Contains(err.Error(), \"descendants: issues filter\") {\n        return getDescendantsUnfiltered(ctx, id) // fallback: filter in Go\n    }\n    return err\n}","preventionTips":["Build filters from types constants, never raw strings.","Keep the filter minimal for descendants queries; post-filter in application code.","After library upgrades, re-check that all populated filter fields are supported by BuildIssueFilterClauses.","Unit-test filter construction paths your code uses."],"tags":["filter","validation","descendants"],"backgroundTag":"invalid-issue-filter","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}