{"record":{"id":"4fa007349ed8314b","repo":"gastownhall/beads","slug":"descendants-wisp-dependencies-probe-w","errorCode":null,"errorMessage":"descendants: wisp_dependencies probe: %w","messagePattern":"descendants: wisp_dependencies probe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/issue_descendants.go","lineNumber":51,"sourceCode":"\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 {\n\t\twispWhereClauses, wispArgs, err = buildIssueFilterClauses(\"\", levelFilter, wispsFilterTables)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"descendants: wisps filter: %w\", err)\n\t\t}\n\t}","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/issue_descendants.go#L33-L69","documentation":"Wraps a failure from optionalTableExists probing the wisp_dependencies table during GetDescendants. The probe runs 'SELECT 1 FROM wisp_dependencies LIMIT 1' and only treats table-not-exist as a clean 'false'; any other probe error (connection, permissions, driver malfunction) is wrapped here and aborts the descendants walk. This decides whether wisp dependencies can be traversed.","triggerScenarios":"Calling GetDescendants when the wisp_dependencies probe fails with something other than sql.ErrNoRows or a recognized table-not-exist error: connection failure, permission denied on the table, corrupted catalog, or context cancellation.","commonSituations":"DB user lacking SELECT on wisp_dependencies, connection dropped between queries, a Dolt server version whose not-exist error isn't recognized by dberrors.IsTableNotExist (version drift), or cancellation timeouts.","solutions":["Read the wrapped cause; if it's a permissions error, grant SELECT on wisp_dependencies or fix the connection user.","Upgrade the storage/dberrors layer if the server's table-not-exist error shape isn't recognized (falls through as a hard error).","Check connectivity and retry — the probe is read-only and cheap.","If wisps are unused in your deployment, set filter.SkipWisps to bypass wisp traversal entirely."],"exampleFix":"// before\ndeps, err := repo.GetDescendants(ctx, id, filter) // hard-fails on probe error\n// after\nfilter.SkipWisps = true // deployment has no wisp tables / no perms\ndeps, err := repo.GetDescendants(ctx, id, filter)","handlingStrategy":"fallback","validationCode":"// pre-probe permissions with the same identity the app uses\nrows, err := db.Query(\"SELECT 1 FROM wisp_dependencies LIMIT 1\")\nif err != nil && !isTableNotExist(err) { log.Printf(\"wisp probe unhealthy: %v\", err) }\nif rows != nil { rows.Close() }","typeGuard":null,"tryCatchPattern":"deps, err := repo.GetDescendants(ctx, id, filter)\nif err != nil {\n    if strings.Contains(err.Error(), \"wisp_dependencies probe\") {\n        filter.SkipWisps = true // degrade: walk issues only\n        return repo.GetDescendants(ctx, id, filter)\n    }\n    return err\n}","preventionTips":["Grant the app DB user SELECT on wisp_dependencies in wisp-enabled deployments.","Set filter.SkipWisps where wisps are not used to skip the probe path entirely.","Keep dberrors/db driver versions aligned with the server so table-not-exist is recognized.","Health-check optional tables at startup rather than mid-request."],"tags":["database","probe","wisp","schema"],"backgroundTag":"table-probe-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}