sipeed/picoclaw · error

create output dir: %w

Error message

create output dir: %w

What it means

Wrapped os.MkdirAll failure at the top of SaveResults in cmd/membench/eval.go. Before writing any per-sample JSON file, the eval harness creates outDir with mode 0755; if the directory cannot be created the error is wrapped with 'create output dir' and propagates, aborting the save phase (results computed so far are not persisted).

Source

Thrown at cmd/membench/eval.go:269

		byCat[cat] = cm
	}
	var overallF1 float64
	if validF1Count > 0 {
		overallF1 = totalF1 / float64(validF1Count)
	}
	return AggMetrics{
		OverallF1:      overallF1,
		OverallHitRate: totalHitRate / float64(nHit),
		ByCategory:     byCat,
		TotalQuestions: len(qaResults),
		ValidF1Count:   validF1Count,
	}
}

// SaveResults writes per-sample eval results to JSON files.
func SaveResults(results []EvalResult, outDir string) error {
	if err := os.MkdirAll(outDir, 0o755); err != nil {
		return fmt.Errorf("create output dir: %w", err)
	}
	for _, r := range results {
		path := filepath.Join(outDir, fmt.Sprintf("eval_%s_%s.json", r.Mode, r.SampleID))
		data, err := json.MarshalIndent(r, "", "  ")
		if err != nil {
			return fmt.Errorf("marshal result: %w", err)
		}
		if err := os.WriteFile(path, data, 0o644); err != nil {
			return fmt.Errorf("write result: %w", err)
		}
	}
	return nil
}

// SaveAggregated writes a combined results.json with all modes.
func SaveAggregated(results []EvalResult, outDir string) error {
	byMode := map[string][]EvalResult{}
	for _, r := range results {

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Point -out at a writable directory you own, e.g. $HOME/membench-results
  2. Remove any regular file occupying the intended directory path, then rerun
  3. Check with os.Stat/os.MkdirAll in a preflight or just mkdir -p the path manually before the run
  4. Free space / fix mount permissions if the error is ENOSPC or EROFS

Example fix

// before
if err := os.MkdirAll(outDir, 0o755); err != nil {
    return fmt.Errorf("create output dir: %w", err)
}

// after (preflight in main before the expensive eval runs)
if err := os.MkdirAll(outDir, 0o755); err != nil {
    return fmt.Errorf("output dir %s not writable: %w", outDir, err)
}
Defensive patterns

Strategy: validation

Validate before calling

if err := os.MkdirAll(outDir, 0o755); err != nil {
    return fmt.Errorf("output dir %s unusable: %w", outDir, err)
}
if f, err := os.CreateTemp(outDir, ".writecheck-"); err != nil {
    return fmt.Errorf("output dir %s not writable: %w", outDir, err)
} else {
    f.Close()
    os.Remove(f.Name())
}

Try / catch

if err := eval.SaveResults(results, outDir); err != nil {
    if errors.Is(err, fs.ErrPermission) || errors.Is(err, fs.ErrNotExist) {
        // fall back to a temp dir so results are not lost after an expensive run
        tmp := filepath.Join(os.TempDir(), "membench-results")
        if err2 := eval.SaveResults(results, tmp); err2 == nil {
            log.Printf("saved to fallback %s", tmp)
            return nil
        }
    }
    return err
}

Prevention

When it happens

Trigger: outDir is inside a read-only mount or one owned by another user (EACCES/EPERM); a parent path component exists as a regular file (ENOTDIR); outDir points to a location like /proc or a full disk (ENOSPC); I/O errors on network storage.

Common situations: Running membench with -out /root/results as non-root; container with a read-only volume mounted at the output path; leftover file named like the output dir; NFS/sshfs hiccup mid-run.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/739c0247d2c6c9ff. Report an issue: GitHub.