{"record":{"id":"fb03334189767c8c","repo":"gastownhall/beads","slug":"get-blocking-info-scan-blocked-by-w","errorCode":null,"errorMessage":"get blocking info: scan blocked-by: %w","messagePattern":"get blocking info: scan blocked-by: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependency_queries.go","lineNumber":627,"sourceCode":"\t\t\tSELECT d.issue_id, %s AS depends_on_id, d.type\n\t\t\tFROM %s d\n\t\t\tWHERE d.issue_id IN (%s) AND d.type IN ('blocks', 'parent-child')\n\t\t`, depTargetExpr(\"d\"), depTable, inClause)\n\n\t\trows, err := tx.QueryContext(ctx, blockedByQuery, args...)\n\t\tif err != nil {\n\t\t\tif optionalBlockedTable(depTable) && isTableNotExistError(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"get blocked-by info from %s: %w\", depTable, err)\n\t\t}\n\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\" {","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependency_queries.go#L609-L645","documentation":"Returned by queryBlockedByInfo when a row of the blocked-by SELECT (issue_id, depends_on_id, type) cannot be scanned into three strings. Typically caused by NULL or non-string values in any of the three columns of dependencies/wisp_dependencies, or schema drift.","triggerScenarios":"Calling GetBlockingInfoForIssuesInTx when a dependency row has NULL issue_id, depends_on_id (per depTargetExpr), or type; or columns were altered to incompatible types by migration/hand-editing.","commonSituations":"Hand-edited or imported data with NULLs; partial schema migrations; rows restored from a mismatched-version backup; driver type-mapping differences after an upgrade.","solutions":["Inspect the wrapped scan error to identify the failing column and value.","Find and repair rows with NULLs: SELECT * FROM <dep table> WHERE issue_id IS NULL OR type IS NULL OR depends_on_id IS NULL.","Re-run schema migrations to restore expected column definitions.","Restore the database from a known-good backup if rows are corrupted.","Align driver/server versions to avoid conversion differences."],"exampleFix":"// before: dependency row with NULL type fails Scan\nINSERT INTO dependencies (issue_id, depends_on_id, type) VALUES ('bd-1', 'bd-2', NULL);\n\n// after: always set the required columns\nINSERT INTO dependencies (issue_id, depends_on_id, type) VALUES ('bd-1', 'bd-2', 'blocks');","handlingStrategy":"validation","validationCode":"// Go: pre-check for unscannable (NULL) columns in dependency rows\nvar n int\nif err := tx.QueryRowContext(ctx,\n    \"SELECT COUNT(*) FROM dependencies WHERE issue_id IS NULL OR depends_on_id IS NULL OR type IS NULL\").Scan(&n); err != nil {\n    return err\n}\nif n > 0 {\n    return fmt.Errorf(\"%d dependency rows have NULL columns; repair first\", n)\n}","typeGuard":"func isScanBlockedByError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"scan blocked-by\")\n}","tryCatchPattern":"blockedBy, blocks, parents, err := GetBlockingInfoForIssuesInTx(ctx, tx, ids)\nif err != nil && isScanBlockedByError(err) {\n    // locate and repair the offending row before retrying\n    return repairNullDependencyRows(ctx, tx)\n}","preventionTips":["Declare issue_id, depends_on_id and type as NOT NULL.","Sanitize any data imported from external sources before insert.","Never leave type NULL — it must be 'blocks' or 'parent-child'.","Run bd doctor after restores to detect NULL/type drift."],"tags":["database","scan-error","null-value","schema-mismatch"],"backgroundTag":"sql-row-scan-type-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}