{"record":{"id":"03750efea1d287c6","repo":"plandex-ai/plandex","slug":"error-rejecting-plan-files-v","errorCode":null,"errorMessage":"error rejecting plan files: %v","messagePattern":"error rejecting plan files: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/result_helpers.go","lineNumber":932,"sourceCode":"\t\t\t\t\terrCh <- fmt.Errorf(\"panic in RejectPlanFiles: %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\t\t\terr := RejectPlanFile(orgId, planId, file, now)\n\n\t\t\tif err != nil {\n\t\t\t\terrCh <- err\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\terrCh <- nil\n\t\t}(file)\n\t}\n\n\tfor i := 0; i < len(files); i++ {\n\t\terr := <-errCh\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error rejecting plan files: %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc RejectPlanFile(orgId, planId, filePathOrResultId string, now time.Time) error {\n\tresultsDir := getPlanResultsDir(orgId, planId)\n\tresults, err := GetPlanFileResults(orgId, planId)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting plan file results: %v\", err)\n\t}\n\n\terrCh := make(chan error, len(results))\n\n\tfor _, result := range results {\n\t\tgo func(result *PlanFileResult) {","sourceCodeStart":914,"sourceCodeEnd":950,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/result_helpers.go#L914-L950","documentation":"RejectPlanFiles waits on errCh once per file and wraps the first worker failure as 'error rejecting plan files: %v'. Any RejectPlanFile error (including getting results, panics, or per-result write failures) is aggregated here.","triggerScenarios":"RejectPlanFile returns an error for any of the fanned-out files: GetPlanFileResults fails, result files unreadable/unwritable, or a recovered panic occurs.","commonSituations":"Results directory missing or unreadable for the given org/plan; one bad file causing repeated failures; concurrent rejection of the same files from two requests.","solutions":["Read the wrapped %v to find which file and underlying error failed","Verify the plan results directory exists and is readable/writable before calling RejectPlanFiles","Ensure the same files are not being rejected concurrently from multiple requests","Log and continue per file if partial rejection is acceptable instead of failing fast"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(getPlanResultsDir(orgId, planId)); os.IsNotExist(err) {\n    return nil // nothing to reject; skip the call\n}\n// pre-check inputs\nfor _, f := range files { if f == \"\" { return fmt.Errorf(\"empty file path\") } }","typeGuard":null,"tryCatchPattern":"if err := RejectPlanFiles(orgId, planId, files, now); err != nil {\n    log.Printf(\"rejecting plan files failed: %v\", err)\n    // retry once after checking filesystem health, or fall back to per-file RejectPlanFile\n}","preventionTips":["Check the results directory exists and is writable before batch rejection","Don't invoke RejectPlanFiles concurrently for the same plan from multiple requests","Log per-file outcomes by calling RejectPlanFile individually if partial success is acceptable","Keep input validation (orgId, planId, file list) at the API boundary"],"tags":["go","error-wrapping","concurrency","fan-out"],"backgroundTag":"batch-operation-partial-failure","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}