{"record":{"id":"674149f867be0523","repo":"plandex-ai/plandex","slug":"error-reading-result-file-v","errorCode":null,"errorMessage":"error reading result file: %v","messagePattern":"error reading result file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/result_helpers.go","lineNumber":411,"sourceCode":"\terrCh := make(chan error, len(files))\n\tresultCh := make(chan *PlanFileResult, len(files))\n\n\tfor _, file := range files {\n\t\t// log.Printf(\"Result file: %s\", file.Name())\n\n\t\tgo func(file os.DirEntry) {\n\t\t\tdefer func() {\n\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\tlog.Printf(\"panic in GetPlanFileResults: %v\\n%s\", r, debug.Stack())\n\t\t\t\t\terrCh <- fmt.Errorf(\"panic in GetPlanFileResults: %v\\n%s\", r, debug.Stack())\n\t\t\t\t\truntime.Goexit() // don't allow outer function to continue and double-send to channel\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\tbytes, err := os.ReadFile(filepath.Join(resultsDir, file.Name()))\n\n\t\t\tif err != nil {\n\t\t\t\terrCh <- fmt.Errorf(\"error reading result file: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar result PlanFileResult\n\t\t\terr = json.Unmarshal(bytes, &result)\n\n\t\t\tif err != nil {\n\t\t\t\terrCh <- fmt.Errorf(\"error unmarshalling result file: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tresultCh <- &result\n\t\t}(file)\n\t}\n\n\tfor i := 0; i < len(files); i++ {\n\t\tselect {\n\t\tcase err := <-errCh:","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/result_helpers.go#L393-L429","documentation":"The per-file goroutine in GetPlanFileResults calls os.ReadFile on the result file; any read failure (permissions, file vanished between listing and reading, I/O error) is reported on errCh as this wrapped error including the underlying os error.","triggerScenarios":"File deleted or renamed by another process after ReadDir listed it; permission denied on the file; symlink pointing to a missing target.","commonSituations":"Concurrent cleanup of result files while GetPlanFileResults iterates; results synced/rotated externally; read-only or stale NFS mounts.","solutions":["Verify no concurrent job deletes files from the results directory during listing","Check file permissions and ownership of the result JSON files","Re-run the call; a race with cleanup is often transient","Hardening: skip files that disappear mid-read instead of failing the whole call"],"exampleFix":"// before\nif err != nil {\n    errCh <- fmt.Errorf(\"error reading result file: %v\", err)\n    return\n}\n// after: tolerate files removed concurrently\nif err != nil {\n    if os.IsNotExist(err) {\n        return // file was deleted during listing\n    }\n    errCh <- fmt.Errorf(\"error reading result file: %v\", err)\n    return\n}","handlingStrategy":"retry","validationCode":"fi, err := os.Stat(filepath.Join(dir, name))\nif err != nil { log.Printf(\"result file missing/unreadable: %s\", name) }","typeGuard":null,"tryCatchPattern":"results, err := db.GetPlanFileResults(orgId, planId)\nif err != nil && strings.Contains(err.Error(), \"error reading result file\") {\n    time.Sleep(100 * time.Millisecond)\n    results, err = db.GetPlanFileResults(orgId, planId) // transient deletion race\n}","preventionTips":["Avoid deleting result files while readers are active","Use atomic rename when cleaning up results","Check for symlink/permission issues on the results dir"],"tags":["go","filesystem","io","concurrency"],"backgroundTag":"file-read-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}