Skip to content

fix(cli): a short CSV write and a zero-result run both print "CSV report written to" #2004

Description

@cristim

Summary

writeMultiServiceCSVReport defers writer.Flush() and never reads writer.Error(), so a failed flush (full disk, failing network mount) loses the header and rows while the function returns nil. Separately it returns nil before os.Create when there are no results. Both callers print "CSV report written to: " on any nil return, so the operator is told a file exists that is truncated, empty or absent. For a --purchase run that CSV is the only record of what was bought.

Location

  • cmd/multi_service_csv.go:194-196 and :208-209 at 3c0f8ac
  • cmd/multi_service.go:175-179 and :579-583 (callers print "written to" on nil)

Failure scenario

A --purchase run writes its report to a mount that fails mid-flush. Flush errors inside the defer, nothing inspects it, and the CLI prints the success line over a zero-byte file. In a run with nothing to purchase, the same line names a file that was never created.

Evidence

func writeMultiServiceCSVReport(results []common.PurchaseResult, filepath string) error {
	if len(results) == 0 {
		return nil
	}
	...
	writer := csv.NewWriter(file)
	defer writer.Flush()

Suggested fix

Call writer.Flush() explicitly before returning and return writer.Error(); return a sentinel (or have the callers check len(results)) so the "written to" line prints only when a file was written.


Found by the 2026-09-02 codebase audit, finding A10-009, reported by one reviewer and independently confirmed by a second. Full report: docs/audits/codebase-audit-2026-09-02.md.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions