{"record":{"id":"349d4eefae09fad7","repo":"gastownhall/beads","slug":"scan-remaining-blocker-w","errorCode":null,"errorMessage":"scan remaining blocker: %w","messagePattern":"scan remaining blocker: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependency_queries.go","lineNumber":856,"sourceCode":"\t\tremainingByCandidate := make(map[string][]string, len(batch))\n\t\tremainingBlockerSet := make(map[string]struct{})\n\t\tfor _, depTable := range []string{\"dependencies\", \"wisp_dependencies\"} {\n\t\t\t//nolint:gosec // G201: depTable is hardcoded.\n\t\t\tdepRows, err := tx.QueryContext(ctx, fmt.Sprintf(`\n\t\t\t\tSELECT issue_id, %s AS depends_on_id FROM %s\n\t\t\t\tWHERE issue_id IN (%s) AND type = 'blocks' AND %s != ?\n\t\t\t`, DepTargetExpr, depTable, placeholders, DepTargetExpr), append(batchArgs, closedIssueID)...)\n\t\t\tif err != nil {\n\t\t\t\tif optionalBlockedTable(depTable) && isTableNotExistError(err) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"check remaining blockers from %s: %w\", depTable, err)\n\t\t\t}\n\t\t\tfor depRows.Next() {\n\t\t\t\tvar candidateID, blockerID string\n\t\t\t\tif err := depRows.Scan(&candidateID, &blockerID); err != nil {\n\t\t\t\t\t_ = depRows.Close()\n\t\t\t\t\treturn nil, fmt.Errorf(\"scan remaining blocker: %w\", err)\n\t\t\t\t}\n\t\t\t\tremainingByCandidate[candidateID] = append(remainingByCandidate[candidateID], blockerID)\n\t\t\t\tremainingBlockerSet[blockerID] = struct{}{}\n\t\t\t}\n\t\t\t_ = depRows.Close()\n\t\t\tif err := depRows.Err(); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"remaining blocker rows from %s: %w\", depTable, err)\n\t\t\t}\n\t\t}\n\n\t\tremainingBlockerIDs := make([]string, 0, len(remainingBlockerSet))\n\t\tfor blockerID := range remainingBlockerSet {\n\t\t\tremainingBlockerIDs = append(remainingBlockerIDs, blockerID)\n\t\t}\n\t\tsort.Strings(remainingBlockerIDs)\n\t\tstatusByID, err := loadStatusByIDInTx(ctx, tx, remainingBlockerIDs)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"check remaining blocker status: %w\", err)","sourceCodeStart":838,"sourceCodeEnd":874,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependency_queries.go#L838-L874","documentation":"Wraps a rows.Scan failure while reading (candidateID, blockerID) string pairs from a dependency-table result set in GetNewlyUnblockedByCloseInTx. This means the query returned rows whose columns could not be scanned into two strings — almost always a schema/type mismatch. The row iteration is aborted and the whole unblock computation fails.","triggerScenarios":"The dependency table's columns have unexpected types (e.g. integer IDs instead of text, NULL values in non-nullable-expected columns, or extra/reordered columns) when GetNewlyUnblockedByCloseInTx iterates remaining blockers.","commonSituations":"Schema drift after an upgrade or hand-edited database; a custom dep table variant whose ID columns are not TEXT; corrupted rows containing NULLs.","solutions":["Inspect the wrapped driver error for the column/type that failed to scan","Verify the dependency table columns are TEXT and NOT NULL as the schema expects","Repair or recreate the table from the canonical schema/migrations","Re-run the close/unblock operation after fixing the schema"],"exampleFix":"// before\nvar candidateID, blockerID string\nrows.Scan(&candidateID, &blockerID) // panics/error on NULL\n// after (schema side: ensure columns are TEXT NOT NULL)\nSELECT COALESCE(issue_id,''), COALESCE(target_id,'') FROM ...","handlingStrategy":"try-catch","validationCode":"// verify dep table column types are TEXT\nrows, _ := db.Query(\"PRAGMA table_info(deps)\")\n// or run bd doctor schema checks before batch operations","typeGuard":null,"tryCatchPattern":"if err := tx.CloseIssue(ctx, id); err != nil {\n\tif strings.Contains(err.Error(), \"scan remaining blocker\") {\n\t\t// schema drift: run migrations / repair before retry\n\t}\n\treturn err\n}","preventionTips":["Never hand-edit or externally write dependency tables","Run migrations on upgrade before using the CLI","Validate schema with bd doctor after restores or syncs"],"tags":["go","sql","scan","schema-mismatch"],"backgroundTag":"row-scan-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}