Summary
Issue #62541 (itself a refile of #60738, the bufioscannererunchecked block scope state reset bug) auto-expired closed as not_planned since the last run, but the underlying code is 100 percent unchanged. This is the second reverse phantom close for this exact bug lineage (60738 then 62541 then this refile), and the general block_scope_state_reset pattern class has now recurred across multiple linters in this repository (bufferresetbeforereuse, bufioscannererunchecked).
Evidence
Re-read pkg/linters/bufioscannererunchecked/bufioscannererunchecked.go lines 71-100. analyzeBlockStatements is invoked independently per *ast.BlockStmt, *ast.CaseClause, and *ast.CommClause via the ast.Inspect walk in analyzeFuncBody (lines 52-62). Inside analyzeBlockStatements, line 98 only searches hasScannerErrCheck(pass, stmts[i+1:], scanner) within that same stmts slice. A scanner.Err() check placed in an ENCLOSING block, after an if, for, or switch statement that wraps the scan loop, lives in a different stmts slice from the loop itself and is therefore invisible to this search.
Impact
A function that wraps a bufio.Scanner loop inside an if or for block, then checks scanner.Err() immediately after that wrapping block closes (in the outer function body), has its Err() check completely missed, producing a false positive unchecked-scanner-error diagnostic even though the error is genuinely checked. bufioscannererunchecked is not CI-enforced (absent from .github/workflows/cgo.yml LINTER_FLAGS), so this does not break CI today, but it is a real, reproducible, untested gap. testdata/src/bufioscannererunchecked only covers an Err() check inside the SAME block as the loop, never the enclosing-block case.
Recommendation
Have analyzeBlockStatements accept or look up the enclosing sequence of statements (for example via a parent-block map built once per function, similar to the parent-tracking approach already used in uncheckedsliceindex.go) so hasScannerErrCheck can continue searching into the statements that follow the ENTIRE wrapping block, not just the remainder of the innermost block.
Validation checklist
- Add a nested-block test fixture where the scan loop is inside an if or for block and the Err() check is placed immediately after that block closes, expecting no diagnostic
- Confirm existing same-block Err() check cases remain unflagged
- Run go test ./pkg/linters/bufioscannererunchecked/...
Effort: medium, requires a parent-block lookup mechanism rather than a single line fix.
Generated by 🤖 Sergo - Serena Go Expert · claude · agent · 258.2 AIC · ⌖ 4.64 AIC · ⊞ 4.9K · ◷
Summary
Issue #62541 (itself a refile of #60738, the bufioscannererunchecked block scope state reset bug) auto-expired closed as not_planned since the last run, but the underlying code is 100 percent unchanged. This is the second reverse phantom close for this exact bug lineage (60738 then 62541 then this refile), and the general block_scope_state_reset pattern class has now recurred across multiple linters in this repository (bufferresetbeforereuse, bufioscannererunchecked).
Evidence
Re-read pkg/linters/bufioscannererunchecked/bufioscannererunchecked.go lines 71-100. analyzeBlockStatements is invoked independently per *ast.BlockStmt, *ast.CaseClause, and *ast.CommClause via the ast.Inspect walk in analyzeFuncBody (lines 52-62). Inside analyzeBlockStatements, line 98 only searches hasScannerErrCheck(pass, stmts[i+1:], scanner) within that same stmts slice. A scanner.Err() check placed in an ENCLOSING block, after an if, for, or switch statement that wraps the scan loop, lives in a different stmts slice from the loop itself and is therefore invisible to this search.
Impact
A function that wraps a bufio.Scanner loop inside an if or for block, then checks scanner.Err() immediately after that wrapping block closes (in the outer function body), has its Err() check completely missed, producing a false positive unchecked-scanner-error diagnostic even though the error is genuinely checked. bufioscannererunchecked is not CI-enforced (absent from .github/workflows/cgo.yml LINTER_FLAGS), so this does not break CI today, but it is a real, reproducible, untested gap. testdata/src/bufioscannererunchecked only covers an Err() check inside the SAME block as the loop, never the enclosing-block case.
Recommendation
Have analyzeBlockStatements accept or look up the enclosing sequence of statements (for example via a parent-block map built once per function, similar to the parent-tracking approach already used in uncheckedsliceindex.go) so hasScannerErrCheck can continue searching into the statements that follow the ENTIRE wrapping block, not just the remainder of the innermost block.
Validation checklist
Effort: medium, requires a parent-block lookup mechanism rather than a single line fix.