Linter: fprintferrorunchecked (76th registered analyzer, PR #65073, added 2026-10-02, first-ever audit)
Problem
The entire analysis is gated by a single nodeFilter entry:
nodeFilter := []ast.Node{(*ast.AssignStmt)(nil)}
(fprintferrorunchecked.go:40). checkUncheckedFprintAssign only recognizes the explicit-blank-assignment shapes _ = fmt.Fprintf(...) and _, _ = fmt.Fprintf(...). A bare statement call with no assignment at all, e.g. fmt.Fprintf(w, "text"), is legal Go that silently discards both return values -- exactly the write-failure-ignored case this linter exists to catch -- yet it never reaches checkUncheckedFprintAssign because there is no AssignStmt node for it.
Evidence
Grep across pkg/ (excluding _test.go) for the bare-statement shape ^\tfmt\.(Fprintf|Fprintln|Fprint)\( returned 938 matches across 193 files -- vastly more common than the explicit _, _ = form this linter actually detects. Two concrete production sites:
- pkg/console/confirm.go:53-56 --
fmt.Fprintf(out, ...) writing to an io.Writer parameter (e.g. os.Stdout in real callers), with zero error handling. This is precisely the silently-ignored-write-failure scenario described in the linters own diagnostic message.
- pkg/workflow/workflow_errors.go:99 --
fmt.Fprintf(&b, ...) building an error string via bytes.Buffer.
CI enforcement
.github/workflows/cgo.yml LINTER_FLAGS already include -fprintferrorunchecked on both the native (line 1487) and wasm (line 1490) custom-linter steps with -test=false, so this gate is active in CI today while being structurally blind to the overwhelming majority of real Fprint* call sites in the codebase.
Pattern class: node_filter_too_narrow (same class previously found in globwalkignorederror/strconvparseignorederror, issues #61265/#63094), but at far larger scale here -- 938 live occurrences versus a handful in prior instances of this class.
Recommendation
Add an *ast.ExprStmt case alongside the existing *ast.AssignStmt case in run() (fprintferrorunchecked.go:40-50): unwrap the ExprStmt to its *ast.CallExpr, then reuse the existing extractFunctionName / isFprintFunction / isFprintCallReturningError / reportUncheckedFprint helpers unchanged.
Validation checklist
Effort: small -- one new ExprStmt branch reusing all existing helper functions.
Generated by 🤖 Sergo - Serena Go Expert · claude · agent · 317.8 AIC · ⌖ 7.26 AIC · ⊞ 5.3K · ◷
Linter: fprintferrorunchecked (76th registered analyzer, PR #65073, added 2026-10-02, first-ever audit)
Problem
The entire analysis is gated by a single nodeFilter entry:
(fprintferrorunchecked.go:40). checkUncheckedFprintAssign only recognizes the explicit-blank-assignment shapes
_ = fmt.Fprintf(...)and_, _ = fmt.Fprintf(...). A bare statement call with no assignment at all, e.g.fmt.Fprintf(w, "text"), is legal Go that silently discards both return values -- exactly the write-failure-ignored case this linter exists to catch -- yet it never reaches checkUncheckedFprintAssign because there is no AssignStmt node for it.Evidence
Grep across pkg/ (excluding _test.go) for the bare-statement shape
^\tfmt\.(Fprintf|Fprintln|Fprint)\(returned 938 matches across 193 files -- vastly more common than the explicit_, _ =form this linter actually detects. Two concrete production sites:fmt.Fprintf(out, ...)writing to an io.Writer parameter (e.g. os.Stdout in real callers), with zero error handling. This is precisely the silently-ignored-write-failure scenario described in the linters own diagnostic message.fmt.Fprintf(&b, ...)building an error string via bytes.Buffer.CI enforcement
.github/workflows/cgo.yml LINTER_FLAGS already include -fprintferrorunchecked on both the native (line 1487) and wasm (line 1490) custom-linter steps with -test=false, so this gate is active in CI today while being structurally blind to the overwhelming majority of real Fprint* call sites in the codebase.
Pattern class: node_filter_too_narrow (same class previously found in globwalkignorederror/strconvparseignorederror, issues #61265/#63094), but at far larger scale here -- 938 live occurrences versus a handful in prior instances of this class.
Recommendation
Add an
*ast.ExprStmtcase alongside the existing*ast.AssignStmtcase in run() (fprintferrorunchecked.go:40-50): unwrap the ExprStmt to its*ast.CallExpr, then reuse the existing extractFunctionName / isFprintFunction / isFprintCallReturningError / reportUncheckedFprint helpers unchanged.Validation checklist
fmt.Fprintf(w, "text")as a standalone ExprStmt, expecting a diagnosticmake golint-custom LINTER_FLAGS="-fprintferrorunchecked -test=false"against pkg/console and pkg/workflow to confirm the fix surfaces new findings without introducing false positives on checked callsEffort: small -- one new ExprStmt branch reusing all existing helper functions.