JuliusBrussee/caveman · error

report path is required

Error message

report path is required

What it means

Returned by Store.WriteLearnHTML when outPath is the empty string. The report writer refuses to guess a destination — it creates the parent directory and writes a 0600 HTML file at exactly the path given, so an empty path is a caller programming error, not an environmental failure.

Source

Thrown at proxy/internal/store/report.go:80

	history := filepath.Join(dir, "caveman-learn."+now.UTC().Format("2006-01-02")+".json")
	if err := os.WriteFile(history, raw, 0o600); err != nil {
		return "", err
	}
	if err := os.Chmod(history, 0o600); err != nil {
		return "", err
	}
	entries, _ := filepath.Glob(filepath.Join(dir, "caveman-learn.????-??-??.json"))
	sort.Strings(entries)
	for len(entries) > 8 {
		_ = os.Remove(entries[0])
		entries = entries[1:]
	}
	return current, nil
}

func (s *Store) WriteLearnHTML(plan LearnPlan, outPath string) error {
	if outPath == "" {
		return fmt.Errorf("report path is required")
	}
	if err := os.MkdirAll(filepath.Dir(outPath), 0o700); err != nil {
		return err
	}
	f, err := os.OpenFile(outPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o600)
	if err != nil {
		return err
	}
	defer f.Close()
	return learnTemplate.Execute(f, struct {
		Plan      LearnPlan
		Generated string
	}{Plan: plan, Generated: time.Now().UTC().Format(time.RFC3339)})
}

func (s *Store) WriteTrialHTML(plan TrialPlan, outPath string) error {
	if outPath == "" {
		return fmt.Errorf("report path is required")

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Default the output path when the flag is empty (e.g. filepath.Join(home, "learn", "index.html")) or reject it at the CLI layer with a clear 'missing --out' message before calling the store
  2. Fix the caller to derive the path from a known-good base directory
  3. Add a unit test that the command fails fast on a missing out path rather than reaching the store

Example fix

// before
err := st.WriteLearnHTML(plan, outPath) // outPath == "" when --out omitted

// after
if outPath == "" {
    return fmt.Errorf("missing --out: learn HTML destination is required")
}
err := st.WriteLearnHTML(plan, outPath)
Defensive patterns

Strategy: validation

Validate before calling

func requireOutPath(p string) (string, error) {
    p = strings.TrimSpace(p)
    if p == "" { return "", errors.New("--out is required for learn HTML") }
    return p, nil
}

Type guard

func hasOutPath(p string) bool { return strings.TrimSpace(p) != "" }

Try / catch

if err := st.WriteLearnHTML(plan, outPath); err != nil {
    if strings.Contains(err.Error(), "report path is required") {
        return usageError("missing --out") // surface a CLI usage message, not a raw store error
    }
    return err
}

Prevention

When it happens

Trigger: Calling WriteLearnHTML(plan, "") — typically because a --out flag was omitted and its zero-value empty string was passed straight through, or a path-building helper returned "" on error and the error was ignored.

Common situations: A CLI command where the output flag is optional but the code does not default it; filepath.Join with an empty base producing an unintended empty; refactoring that dropped the path argument's assignment.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/795249b400fcf136. Report an issue: GitHub.