{"record":{"id":"7613c4509b225c12","repo":"plandex-ai/plandex","slug":"planid-field-is-required","errorCode":null,"errorMessage":"planId field is required","messagePattern":"planId field is required","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"app/server/handlers/projects.go","lineNumber":157,"sourceCode":"\t// read the request body\n\tbody, err := io.ReadAll(r.Body)\n\tif err != nil {\n\t\tlog.Printf(\"Error reading request body: %v\\n\", err)\n\t\thttp.Error(w, \"Error reading request body\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer r.Body.Close()\n\n\tvar requestBody shared.SetProjectPlanRequest\n\tif err := json.Unmarshal(body, &requestBody); err != nil {\n\t\tlog.Printf(\"Error parsing request body: %v\\n\", err)\n\t\thttp.Error(w, \"Error parsing request body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tif requestBody.PlanId == \"\" {\n\t\tlog.Println(\"Received empty planId field\")\n\t\thttp.Error(w, \"planId field is required\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t// update statement here -- need auth / current user id\n\n\tlog.Println(\"Successfully set project plan\", projectId)\n}\n\nfunc RenameProjectHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for RenameProjectHandler\")\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tvars := mux.Vars(r)\n\tprojectId := vars[\"projectId\"]\n","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/projects.go#L139-L175","documentation":"This is a field-validation error: the parsed SetProjectPlanRequest has an empty PlanId, so the handler rejects the request with HTTP 400 'planId field is required' before applying the update. Like error 1040, it enforces that the required plan identifier is present.","triggerScenarios":"POST to the project set-plan endpoint with valid JSON but no \"planId\" key, \"planId\": \"\", or \"planId\": null (decodes to empty string).","commonSituations":"Client never resolved/selected a plan before calling set-plan; renamed field in client code (plan vs planId); stubbed client sending a placeholder empty payload; older client versions predating the planId field.","solutions":["Include a non-empty \"planId\" string in the JSON body: {\"planId\":\"<plan-id>\"}.","Fix the client to obtain a real plan id (create or look up the plan) before calling this endpoint.","Guard on the client: skip/queue the call when the plan id is empty instead of sending an empty one.","If testing, use a plan id from a prior create-plan response."],"exampleFix":"// before\n{\"planId\": \"\"}\n// after\n{\"planId\": \"01f3d0e9-8a2c-4b7e-9d1a-2c3b4d5e6f7a\"}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(planId) == \"\" {\n\treturn errors.New(\"planId field is required\")\n}","typeGuard":"func hasPlanId(req shared.SetProjectPlanRequest) bool {\n\treturn strings.TrimSpace(req.PlanId) != \"\"\n}","tryCatchPattern":null,"preventionTips":["Resolve the plan id (create or fetch the plan) before calling set-plan.","Disable/delay the set-plan UI action until a plan id exists.","Mirror server validation client-side to fail fast with a clear message.","Use the shared request struct so field names can't drift."],"tags":["http","validation","go","bad-request"],"backgroundTag":"missing-required-argument","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"}