{"record":{"id":"a47d92618904651b","repo":"gastownhall/beads","slug":"scan-dependent-w-a47d92","errorCode":null,"errorMessage":"scan dependent: %w","messagePattern":"scan dependent: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/delete_role.go","lineNumber":213,"sourceCode":"\t\t}\n\t\tinClause, args := buildSQLInClause(ids[i:end])\n\n\t\tfor _, depTable := range []string{\"dependencies\", \"wisp_dependencies\"} {\n\t\t\trows, err := tx.QueryContext(ctx,\n\t\t\t\tfmt.Sprintf(`SELECT %s AS depends_on_id, issue_id FROM %s WHERE %s`,\n\t\t\t\t\tDepTargetExpr, depTable, depTargetIn(\"\", inClause)),\n\t\t\t\targs...)\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(\"query dependents from %s: %w\", depTable, err)\n\t\t\t}\n\t\t\tfor rows.Next() {\n\t\t\t\tvar target, dependent string\n\t\t\t\tif err := rows.Scan(&target, &dependent); err != nil {\n\t\t\t\t\t_ = rows.Close()\n\t\t\t\t\treturn nil, fmt.Errorf(\"scan dependent: %w\", err)\n\t\t\t\t}\n\t\t\t\tif idSet[dependent] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif bySource[target] == nil {\n\t\t\t\t\tbySource[target] = make(map[string]bool)\n\t\t\t\t}\n\t\t\t\tbySource[target][dependent] = true\n\t\t\t}\n\t\t\t_ = rows.Close()\n\t\t\tif err := rows.Err(); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"iterate dependents from %s: %w\", depTable, err)\n\t\t\t}\n\t\t}\n\t}\n\n\tout := make(map[string][]string, len(bySource))\n\tfor target, dependents := range bySource {","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/delete_role.go#L195-L231","documentation":"While iterating rows returned by the external-dependents query, rows.Scan failed to decode the two expected string columns (depends_on_id, issue_id). This almost always means the row shape returned by the backend does not match the query — e.g. a NULL in a column scanned into a string, or a modified DepTargetExpr changing column type/arity. Rows are closed before returning.","triggerScenarios":"ExternalDependentsBySourceInTx loops rows.Next() on the dependencies/wisp_dependencies query and Scan(&target, &dependent) errors — NULL values in scanned columns, driver type mismatch, or altered SELECT shape.","commonSituations":"Dependency rows with NULL issue_id or NULL target expression written by an older version or external tool; a customized DepTargetExpr returning a non-string type; backend driver returning column types the scan cannot coerce.","solutions":["Find the offending row: SELECT ... WHERE issue_id IS NULL OR target IS NULL on the named dependency table, and repair it","Check whether DepTargetExpr was customized and still yields a plain string column","Verify dependency rows were not hand-edited or written by an incompatible schema version","Re-run the delete after repairing the row; the scan fails deterministically on the same row until fixed"],"exampleFix":"// before: NULL target breaks the string scan\nrows, _ := tx.QueryContext(ctx, \"SELECT dep_target, issue_id FROM dependencies WHERE ...\")\n// after (repair the data first):\nUPDATE dependencies SET target_id = '<valid-id>' WHERE target_id IS NULL;","handlingStrategy":"validation","validationCode":"// audit dependency rows for NULLs before deleting\nrows, err := db.Query(\"SELECT issue_id, target_id FROM dependencies WHERE issue_id IS NULL OR target_id IS NULL\")\n// any returned row will crash the scan later; repair it first","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"scan dependent\") {\n    // find and fix the malformed dependency row, then re-run\n}","preventionTips":["Never hand-edit dependency tables; use the library's dep-add/remove APIs","Add a periodic integrity check for NULL dependency columns","Keep schema versions aligned between writer tools","After any external import, validate dependency rows before deletes"],"tags":["database","sql","scan-error","data-integrity"],"backgroundTag":"sql-scan-type-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}