{"record":{"id":"ae0612fa997f13ca","repo":"JuliusBrussee/caveman","slug":"report-path-is-required-stats","errorCode":null,"errorMessage":"report path is required","messagePattern":"report path is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/store/stats_report.go","lineNumber":19,"sourceCode":"package store\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\nfunc DefaultStatsReportPath(home string) string {\n\treturn filepath.Join(home, \"reports\", \"caveman-stats.html\")\n}\n\n// WriteStatsHTML writes a private, self-contained snapshot. The page only rolls\n// up recorded metric groups; it never derives a price or upgrades evidence.\nfunc (s *Store) WriteStatsHTML(report StatsReport, outPath string) error {\n\tif outPath == \"\" {\n\t\treturn fmt.Errorf(\"report path is required\")\n\t}\n\traw, err := json.Marshal(report)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"encode stats report: %w\", err)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(outPath), 0o700); err != nil {\n\t\treturn err\n\t}\n\tf, err := os.CreateTemp(filepath.Dir(outPath), \".caveman-stats-*.html\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer os.Remove(f.Name())\n\t// encoding/json escapes <, >, &, and JavaScript line separators. Mark only\n\t// its output as JavaScript: an untrusted model name cannot close the script.\n\terr = statsReportTemplate.Execute(f, struct{ Data template.JS }{Data: template.JS(raw)})\n\tif closeErr := f.Close(); err == nil {\n\t\terr = closeErr","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/internal/store/stats_report.go#L1-L37","documentation":"WriteStatsHTML writes a private, self-contained stats snapshot HTML file at outPath, rolling up only recorded metric groups. An empty outPath is rejected with 'report path is required' before encoding or writing anything. The page never derives prices, so a path must be supplied explicitly for the snapshot to land somewhere meaningful.","triggerScenarios":"Calling WriteStatsHTML (directly or via runStatsReport) with an empty outPath, typically when the stats report output flag was omitted.","commonSituations":"Missing --out flag in a scheduled stats snapshot job; empty path in a wrapper script; regression after refactoring where the default output path was removed.","solutions":["Pass a concrete output path for the stats HTML snapshot","Set the flag/config value that supplies the path before invoking the command","Validate non-empty in the caller and emit a usage error when blank"],"exampleFix":"// before\nif err := store.WriteStatsHTML(report, outPath); err != nil { ... } // outPath == \"\"\n// after\nif outPath == \"\" {\n    return fmt.Errorf(\"--out is required for the stats report\")\n}\nif err := store.WriteStatsHTML(report, outPath); err != nil { ... }","handlingStrategy":"validation","validationCode":"if outPath == \"\" { return fmt.Errorf(\"stats report output path is required\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Require the stats snapshot output flag in CLI help and wrappers","Default scheduled snapshots to a dated file path","Assert all output paths are non-empty in pre-run checks","Keep default paths defined in one config location to avoid regressions"],"tags":["cli","validation","report"],"backgroundTag":"empty-required-field","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}