{"record":{"id":"098708e27d47c439","repo":"gastownhall/beads","slug":"journal-scan-dependency-removal-from-s-w","errorCode":null,"errorMessage":"journal: scan dependency removal from %s: %w","messagePattern":"journal: scan dependency removal from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/journal_dependencies.go","lineNumber":99,"sourceCode":"\t\tinClause, args := buildSQLInClause(ids[start:end])\n\t\tqueryArgs := append(append([]any{}, args...), args...)\n\t\t//nolint:gosec // table is validated above and inClause contains only placeholders.\n\t\trows, err := tx.QueryContext(ctx, fmt.Sprintf(`\n\t\t\tSELECT issue_id, %s AS target, type, metadata\n\t\t\tFROM %s\n\t\t\tWHERE issue_id IN (%s) OR %s IN (%s)\n\t\t`, DepTargetExpr, table, inClause, DepTargetExpr, inClause), queryArgs...)\n\t\tif err != nil {\n\t\t\tif optionalBlockedTable(table) && isTableNotExistError(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"journal: query dependency removals from %s: %w\", table, err)\n\t\t}\n\t\tfor rows.Next() {\n\t\t\tvar edge journalDependencyEdge\n\t\t\tif err := rows.Scan(&edge.source, &edge.target, &edge.kind, &edge.metadata); err != nil {\n\t\t\t\t_ = rows.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"journal: scan dependency removal from %s: %w\", table, err)\n\t\t\t}\n\t\t\tbyKey[dependencyEdgeKey(edge)] = edge\n\t\t}\n\t\tif err := rows.Err(); err != nil {\n\t\t\t_ = rows.Close()\n\t\t\treturn nil, fmt.Errorf(\"journal: iterate dependency removals from %s: %w\", table, err)\n\t\t}\n\t\tif err := rows.Close(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"journal: close dependency removals from %s: %w\", table, err)\n\t\t}\n\t}\n\treturn sortedDependencyEdges(byKey), nil\n}\n\nfunc dependencyEdgeKey(edge journalDependencyEdge) string {\n\treturn edge.source + \"\\x00\" + edge.target + \"\\x00\" + edge.kind + \"\\x00\" + edge.metadata\n}\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/journal_dependencies.go#L81-L117","documentation":"While scanning dependency-removal edges from one table into journalDependencyEdge (source, target, kind, metadata), rows.Scan failed. This wraps column-count/type mismatches between the queried table's projection and the four-field scanner. The rows are explicitly closed before returning, so the error path is clean.","triggerScenarios":"RecordDependencyRemovalsForTableInTx / dependencyEdgesForIssueIDsInTx encountering rows whose shape differs from the SELECT: schema drift on a dependency table (renamed/dropped/extra columns), NULL in a column scanned into a non-nullable field, or a driver returning unexpected types for kind/metadata.","commonSituations":"Manually altered dependency tables; restoring tables from an older backup with a different schema; a driver version changing how TEXT/JSON metadata is returned.","solutions":["Run migrations/`bd doctor` to reconcile the dependency table schema with the expected projection.","Diff the table's columns against the SELECT in dependencyEdgesInTableForIssueIDsInTx and ALTER to restore the expected shape.","Repair rows with unexpected NULLs in source/target/kind columns.","Align the driver version with the app's tested version."],"exampleFix":"// before\nALTER TABLE issue_dependencies CHANGE kind dep_type VARCHAR(32); -- scanner expects `kind`\n// after\nALTER TABLE issue_dependencies CHANGE dep_type kind VARCHAR(32); -- restore expected column name","handlingStrategy":"validation","validationCode":"cols, _ := db.Query(\"SHOW COLUMNS FROM issue_dependencies\")\nwant := map[string]bool{\"source\": true, \"target\": true, \"kind\": true, \"metadata\": true}\nfor cols.Next() { var c, t, null, key, extra string; _ = cols.Scan(&c, &t, &null, &key, &extra); delete(want, c) }\nif len(want) > 0 { return fmt.Errorf(\"dependency table schema drift, missing: %v\", want) }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"journal: scan dependency removal from\") {\n    return fmt.Errorf(\"dependency table schema drifted vs scanner; reconcile via migrations: %w\", err)\n}","preventionTips":["Let migrations own dependency-table schema; no manual renames.","Restore only matching-version backups.","Check for unexpected NULLs in source/target/kind after imports.","Pin driver versions so TEXT/JSON scanning behavior is stable."],"tags":["storage","database","journal","dependencies","schema-mismatch"],"backgroundTag":"row-scan-type-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}