{"record":{"id":"0fb71abe8fc84660","repo":"gastownhall/beads","slug":"db-dependencysqlrepository-getblockinginfo-inbou","errorCode":null,"errorMessage":"db: DependencySQLRepository.GetBlockingInfo: inbound: %w","messagePattern":"db: DependencySQLRepository\\.GetBlockingInfo: inbound: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/dependency.go","lineNumber":512,"sourceCode":"\n\t//nolint:gosec // G201: table and depTargetExpr are hardcoded constants\n\toutQ := fmt.Sprintf(\n\t\t\"SELECT issue_id, %s AS depends_on_id, type FROM %s WHERE issue_id IN (%s) AND type IN ('blocks', 'parent-child')\",\n\t\tdepTargetExpr, table, idPlaceholders,\n\t)\n\toutRows, err := r.scanBlockingRows(ctx, outQ, idArgs)\n\tif err != nil {\n\t\treturn domain.BlockingInfo{}, fmt.Errorf(\"db: DependencySQLRepository.GetBlockingInfo: outbound: %w\", err)\n\t}\n\n\t//nolint:gosec // G201: table and depTargetExpr are hardcoded constants\n\tinQ := fmt.Sprintf(\n\t\t\"SELECT issue_id, %s AS depends_on_id, type FROM %s WHERE %s IN (%s) AND type = 'blocks'\",\n\t\tdepTargetExpr, table, depTargetExpr, idPlaceholders,\n\t)\n\tinRows, err := r.scanBlockingRows(ctx, inQ, idArgs)\n\tif err != nil {\n\t\treturn domain.BlockingInfo{}, fmt.Errorf(\"db: DependencySQLRepository.GetBlockingInfo: inbound: %w\", err)\n\t}\n\n\tstatusIDs := make(map[string]struct{})\n\tfor _, row := range outRows {\n\t\tstatusIDs[row.dependsOnID] = struct{}{}\n\t}\n\tfor _, row := range inRows {\n\t\tstatusIDs[row.dependsOnID] = struct{}{}\n\t}\n\tstatusByID, err := r.loadStatusByID(ctx, statusIDs)\n\tif err != nil {\n\t\treturn domain.BlockingInfo{}, fmt.Errorf(\"db: DependencySQLRepository.GetBlockingInfo: status lookup: %w\", err)\n\t}\n\n\tfor _, row := range outRows {\n\t\tif statusByID[row.dependsOnID] == types.StatusClosed {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/dependency.go#L494-L530","documentation":"Wraps a failure from the inbound scanBlockingRows query in GetBlockingInfo (SELECT ... WHERE depends_on_id IN (...) AND type='blocks'), which computes the BlockedBy map. The outbound half already succeeded; this failure discards everything and returns an empty BlockingInfo with the error.","triggerScenarios":"GetBlockingInfo(ctx, issueIDs, opts): the inbound SELECT fails or rows fail to scan — connection dropped between the two queries, placeholder limit exceeded, wrong wisps/issues table, corrupted dep rows.","commonSituations":"Same bulk blocking-info contexts as outbound, plus mid-call connection loss where only the second query fails.","solutions":["Retry the whole GetBlockingInfo call; both halves are needed for a consistent result.","Chunk issueIDs to stay within placeholder limits.","Verify UseWispsTable points at the correct deps table.","Check connection health/pool timeouts if the second query repeatedly fails after the first."],"exampleFix":"// before\ninfo, err := deps.GetBlockingInfo(ctx, ids, opts)\nif err != nil { return err } // possibly transient (inbound) failure\n// after\ninfo, err := retry.Do(ctx, 3, backoff, func() (domain.BlockingInfo, error) {\n    return deps.GetBlockingInfo(ctx, ids, opts)\n})","handlingStrategy":"retry","validationCode":"if len(issueIDs) == 0 { return domain.BlockingInfo{}, nil }\nif len(issueIDs) > 500 { /* chunk before calling */ }","typeGuard":null,"tryCatchPattern":"info, err := deps.GetBlockingInfo(ctx, ids, opts)\nif err != nil && strings.Contains(err.Error(), \"GetBlockingInfo: inbound\") {\n    if isTransientDBError(err) {\n        info, err = deps.GetBlockingInfo(ctx, ids, opts) // retry whole call\n    }\n}","preventionTips":["Always retry the entire GetBlockingInfo call so outbound and inbound halves stay consistent.","Chunk IDs to respect placeholder limits.","Ensure the connection pool keeps connections alive through multi-query calls.","Verify the wisps-table flag matches the data location."],"tags":["database","query","blocking"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}