{"record":{"id":"7261ad4a2950b445","repo":"sipeed/picoclaw","slug":"write-result-w","errorCode":null,"errorMessage":"write result: %w","messagePattern":"write result: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/membench/eval.go","lineNumber":278,"sourceCode":"\t\tByCategory:     byCat,\n\t\tTotalQuestions: len(qaResults),\n\t\tValidF1Count:   validF1Count,\n\t}\n}\n\n// SaveResults writes per-sample eval results to JSON files.\nfunc SaveResults(results []EvalResult, outDir string) error {\n\tif err := os.MkdirAll(outDir, 0o755); err != nil {\n\t\treturn fmt.Errorf(\"create output dir: %w\", err)\n\t}\n\tfor _, r := range results {\n\t\tpath := filepath.Join(outDir, fmt.Sprintf(\"eval_%s_%s.json\", r.Mode, r.SampleID))\n\t\tdata, err := json.MarshalIndent(r, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"marshal result: %w\", err)\n\t\t}\n\t\tif err := os.WriteFile(path, data, 0o644); err != nil {\n\t\t\treturn fmt.Errorf(\"write result: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// SaveAggregated writes a combined results.json with all modes.\nfunc SaveAggregated(results []EvalResult, outDir string) error {\n\tbyMode := map[string][]EvalResult{}\n\tfor _, r := range results {\n\t\tbyMode[r.Mode] = append(byMode[r.Mode], r)\n\t}\n\n\taggMap := map[string]AggMetrics{}\n\tfor mode, modeResults := range byMode {\n\t\taggMap[mode] = computeModeAgg(modeResults)\n\t}\n\n\tdata, err := json.MarshalIndent(aggMap, \"\", \"  \")","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/membench/eval.go#L260-L296","documentation":"os.WriteFile failure while persisting an individual eval result file eval_<mode>_<sampleID>.json under outDir. The error wraps the underlying syscall (permission, ENOSPC, ENAMETOOLONG, ENOENT if the directory vanished mid-run). Because the loop aborts on first failure, later samples are not written.","triggerScenarios":"Disk fills up mid-run; outDir deleted or unmounted between MkdirAll and WriteFile; SampleID containing '/' or path separators creating an invalid path; filename exceeding NAME_MAX (255) for long sample IDs; SELinux/AppArmor denying writes.","commonSituations":"Large eval sweeps filling a small tmpfs; container whose volume is rotated mid-run; sample IDs with characters that are legal in the source dataset but illegal in filenames.","solutions":["Check df/space on the output volume and free room, then rerun (ingestion is idempotent via existing-conversation check)","Sanitize SampleID before it reaches the filename: strip '/' and length-cap it","Verify outDir still exists and is writable immediately before the run","Write to a local directory first and sync results off-box, instead of writing directly to network storage"],"exampleFix":"// before\npath := filepath.Join(outDir, fmt.Sprintf(\"eval_%s_%s.json\", r.Mode, r.SampleID))\n\n// after\nsafeID := strings.Map(func(c rune) rune {\n    if c == '/' || c == os.PathSeparator { return '_' }\n    return c\n}, r.SampleID)\npath := filepath.Join(outDir, fmt.Sprintf(\"eval_%s_%s.json\", r.Mode, safeID))","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(outDir); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"%s exists and is a file\", outDir)\n}\n// plus a write-probe as in the mkdir check","typeGuard":null,"tryCatchPattern":"var pathErr *fs.PathError\nif errors.As(err, &pathErr) {\n    switch {\n    case errors.Is(pathErr.Err, syscall.ENOSPC):\n        log.Printf(\"disk full writing %s; freeing space\", pathErr.Path)\n    case errors.Is(pathErr.Err, syscall.ENAMETOOLONG):\n        log.Printf(\"filename too long for sample %s\", r.SampleID)\n    default:\n        log.Printf(\"write failed: %v\", pathErr)\n    }\n}","preventionTips":["Sanitize SampleID (strip path separators, cap length) before it enters a filename","Monitor disk space for long eval sweeps; they write one JSON per sample per mode","Write locally, sync remotely — avoid NFS as the direct output target","Run ingestion idempotently: rerun resumes and rewrites missing files"],"tags":["go","filesystem","benchmark","disk-full"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}