{"record":{"id":"d72ef990ba200d70","repo":"gastownhall/beads","slug":"get-blocking-info-blocker-status-w","errorCode":null,"errorMessage":"get blocking info: blocker status: %w","messagePattern":"get blocking info: blocker status: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependency_queries.go","lineNumber":639,"sourceCode":"\t\tvar depRows []blockingInfoRow\n\t\tvar blockerIDs []string\n\t\tfor rows.Next() {\n\t\t\tvar row blockingInfoRow\n\t\t\tif scanErr := rows.Scan(&row.issueID, &row.blockerID, &row.depType); scanErr != nil {\n\t\t\t\t_ = rows.Close()\n\t\t\t\treturn fmt.Errorf(\"get blocking info: scan blocked-by: %w\", scanErr)\n\t\t\t}\n\t\t\tdepRows = append(depRows, row)\n\t\t\tblockerIDs = append(blockerIDs, row.blockerID)\n\t\t}\n\t\t_ = rows.Close()\n\t\tif err := rows.Err(); err != nil {\n\t\t\treturn fmt.Errorf(\"get blocking info: blocked-by rows: %w\", err)\n\t\t}\n\n\t\tstatusByID, err := loadStatusByIDInTx(ctx, tx, blockerIDs)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"get blocking info: blocker status: %w\", err)\n\t\t}\n\t\tfor _, row := range depRows {\n\t\t\tif statusByID[row.blockerID] == types.StatusClosed {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif row.depType == \"parent-child\" {\n\t\t\t\tparentMap[row.issueID] = row.blockerID\n\t\t\t} else {\n\t\t\t\tblockedByMap[row.issueID] = append(blockedByMap[row.issueID], row.blockerID)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// queryBlocksInfo queries inbound blocking info across dependency tables.\nfunc queryBlocksInfo(","sourceCodeStart":621,"sourceCodeEnd":657,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependency_queries.go#L621-L657","documentation":"Returned by queryBlockedByInfo when loadStatusByIDInTx fails while fetching the close-status of blocker issue IDs, so the library cannot decide which blockers are still active. The %w wraps the underlying status-load error (query failure on the issues table, connection problem, etc.).","triggerScenarios":"Calling GetBlockingInfoForIssuesInTx when the issues table is missing/unreadable, the connection fails during the status lookup, or the batched status query errors — e.g. after a corrupt DB restore or missing grants on the issues table.","commonSituations":"Database missing the issues table (unmigrated DB); SELECT permissions revoked; connection drop between the dependency query and the status lookup; Dolt server errors.","solutions":["Inspect the wrapped error from loadStatusByIDInTx for the root cause (missing table, permissions, connection).","If the issues table is missing, run database initialization/migration.","If permission denied, grant SELECT on the issues table to the DB user.","Retry on transient connection errors; verify remote server health.","If the DB is corrupted, restore from backup or re-sync from the git remote."],"exampleFix":"// before: restricted user cannot read issues table\nGRANT SELECT ON beads.dependencies TO 'bd'@'%';\n\n// after: grant read on all beads tables including issues\nGRANT SELECT ON beads.* TO 'bd'@'%';\nFLUSH PRIVILEGES;","handlingStrategy":"validation","validationCode":"// Go: verify issues table is readable before dependency queries\nvar n int\nif err := tx.QueryRowContext(ctx,\n    \"SELECT COUNT(*) FROM issues LIMIT 1\").Scan(&n); err != nil {\n    return fmt.Errorf(\"issues table unreadable: %w\", err)\n}","typeGuard":"func isBlockerStatusError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"get blocking info: blocker status\")\n}","tryCatchPattern":"blockedBy, blocks, parents, err := GetBlockingInfoForIssuesInTx(ctx, tx, ids)\nif isBlockerStatusError(err) {\n    if isMissingTable(errors.Unwrap(err)) {\n        return runMigrations(ctx, tx)\n    }\n    return fmt.Errorf(\"cannot resolve blocker statuses: %w\", err)\n}","preventionTips":["Ensure migrations create the issues table before dependency features are used.","Grant SELECT on the issues table to the application DB user.","Run read-health checks (SELECT 1, SELECT COUNT(*) FROM issues) before batch operations.","Keep DB restores and client versions in sync."],"tags":["database","sql","status-lookup","missing-table"],"backgroundTag":"sql-no-such-table","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}