{"record":{"id":"6facdc51253c99ee","repo":"plandex-ai/plandex","slug":"error-reading-results-dir-v","errorCode":null,"errorMessage":"error reading results dir: %v","messagePattern":"error reading results dir: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/result_helpers.go","lineNumber":390,"sourceCode":"\t\treturn descriptions[i].CreatedAt.Before(descriptions[j].CreatedAt)\n\t})\n\n\treturn descriptions, nil\n}\n\nfunc GetPlanFileResults(orgId, planId string) ([]*PlanFileResult, error) {\n\tvar results []*PlanFileResult\n\n\tresultsDir := getPlanResultsDir(orgId, planId)\n\n\tfiles, err := os.ReadDir(resultsDir)\n\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn results, nil\n\t\t}\n\n\t\treturn nil, fmt.Errorf(\"error reading results dir: %v\", err)\n\t}\n\n\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()))","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/result_helpers.go#L372-L408","documentation":"GetPlanFileResults lists the plan results directory via os.ReadDir (or similar); on failure it returns this wrapped error. A directory that does not exist is deliberately treated as an empty result, so this error only fires for genuine read failures.","triggerScenarios":"os.ReadDir on the plan results dir fails with a non-NotExist error: permission denied, path exists but is a file, I/O error, or ENOSPC.","commonSituations":"Wrong orgId/planId causing a weird path; results dir deleted or replaced by a file; restrictive file permissions after container/image changes; read-only volume mounts failing.","solutions":["Check the resolved results dir path printed via getPlanResultsDir for correct orgId/planId","Verify directory permissions (read+execute bits) and that it is a directory, not a file","Check mount/disk health (dmesg, df) if it is an I/O error","Note: NotExist is intentionally treated as empty — confirm the error is genuinely a read failure"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"fi, err := os.Stat(resultsDir)\nif err != nil || !fi.IsDir() {\n    // treat as no results; skip or recreate the directory\n}\nif err := unix.Access(resultsDir, unix.R_OK); err != nil {\n    log.Printf(\"results dir not readable: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"results, err := db.GetPlanFileResults(orgId, planId)\nif err != nil {\n    log.Printf(\"plan results unavailable: %v\", err)\n    results = nil // degrade gracefully to empty result set\n}","preventionTips":["Ensure the app creates the results dir (MkdirAll) before use","Check volume mount permissions after deployments","Never replace the results dir with a regular file"],"tags":["go","filesystem","permissions"],"backgroundTag":"directory-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"}