{"record":{"id":"adfc92a97f8a5846","repo":"gastownhall/beads","slug":"scan-blocker-edge-w","errorCode":null,"errorMessage":"scan blocker edge: %w","messagePattern":"scan blocker edge: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependency_queries.go","lineNumber":948,"sourceCode":"\t\tdependsOnID, depType string\n\t}\n\tvar edges []depEdge\n\tfor _, depTable := range []string{\"dependencies\", \"wisp_dependencies\"} {\n\t\trows, err := tx.QueryContext(ctx, fmt.Sprintf(`\n\t\t\tSELECT %s AS depends_on_id, type FROM %s\n\t\t\tWHERE issue_id = ? AND type IN ('blocks', 'waits-for', 'conditional-blocks')\n\t\t`, DepTargetExpr, depTable), issueID)\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 false, nil, fmt.Errorf(\"check blockers from %s: %w\", depTable, err)\n\t\t}\n\t\tfor rows.Next() {\n\t\t\tvar e depEdge\n\t\t\tif err := rows.Scan(&e.dependsOnID, &e.depType); err != nil {\n\t\t\t\t_ = rows.Close()\n\t\t\t\treturn false, nil, fmt.Errorf(\"scan blocker edge: %w\", err)\n\t\t\t}\n\t\t\tedges = append(edges, e)\n\t\t}\n\t\t_ = rows.Close()\n\t\tif err := rows.Err(); err != nil {\n\t\t\treturn false, nil, fmt.Errorf(\"blocker edge rows from %s: %w\", depTable, err)\n\t\t}\n\t}\n\n\tif len(edges) == 0 {\n\t\treturn true, nil, nil\n\t}\n\n\tblockerIDs := make([]string, 0, len(edges))\n\tfor _, e := range edges {\n\t\tblockerIDs = append(blockerIDs, e.dependsOnID)\n\t}\n\tstatusByID, err := loadStatusByIDInTx(ctx, tx, blockerIDs)","sourceCodeStart":930,"sourceCodeEnd":966,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependency_queries.go#L930-L966","documentation":"Wraps a rows.Scan failure while reading (dependsOnID, depType) edge rows in IsBlockedInTx. The edge query succeeded but a returned row could not be scanned into two strings, indicating column type/shape mismatch or NULLs in the dep table.","triggerScenarios":"Iterating blocker edges when a dependency table row has unexpected column types (non-TEXT id/type columns, NULL values) or the table schema differs from what the query expects.","commonSituations":"Hand-edited or externally written dep tables with wrong column types; upgrade-related schema drift; corrupted rows.","solutions":["Check the wrapped scan error to find the offending column","Ensure depends_on/id and type columns are TEXT NOT NULL per schema","Recreate or migrate the dependency table to canonical schema","Re-run the blocked check after repair"],"exampleFix":"// before\nSELECT depends_on_id, type FROM deps WHERE ...\n// after (defensive)\nSELECT COALESCE(depends_on_id,''), COALESCE(type,'') FROM deps WHERE ...","handlingStrategy":"try-catch","validationCode":"// check column types\nrows, _ := db.Query(\"SELECT typeof(depends_on_id), typeof(type) FROM deps LIMIT 1\")","typeGuard":null,"tryCatchPattern":"if err := issueops.IsBlocked(ctx, id); err != nil {\n\tif strings.Contains(err.Error(), \"scan blocker edge\") {\n\t\t// schema drift: fix column types to TEXT, then retry\n\t}\n\treturn err\n}","preventionTips":["Only write dependency edges through bd commands","Validate table schema after external restores/syncs","Keep column types TEXT NOT NULL as defined by migrations"],"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"}