{"record":{"id":"0fc1b039c61e8b6e","repo":"plandex-ai/plandex","slug":"error-scanning-project","errorCode":null,"errorMessage":"Error scanning project: ","messagePattern":"Error scanning project: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/projects.go","lineNumber":107,"sourceCode":"\t\treturn\n\t}\n\n\trows, err := db.Conn.Query(\"SELECT id, name FROM projects WHERE org_id = $1\", auth.OrgId)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error listing projects: %v\\n\", err)\n\t\thttp.Error(w, \"Error listing projects: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tvar projects []shared.Project\n\n\tfor rows.Next() {\n\t\tvar project shared.Project\n\t\terr := rows.Scan(&project.Id, &project.Name)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Error scanning project: %v\\n\", err)\n\t\t\thttp.Error(w, \"Error scanning project: \"+err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tprojects = append(projects, project)\n\t}\n\n\tbytes, err := json.Marshal(projects)\n\tif err != nil {\n\t\tlog.Printf(\"Error marshalling projects: %v\\n\", err)\n\t\thttp.Error(w, \"Error marshalling projects: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Write(bytes)\n}\n\nfunc ProjectSetPlanHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for UpdateProjectSetPlanHandler\")\n\tauth := Authenticate(w, r, true)","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/projects.go#L89-L125","documentation":"While iterating query rows, rows.Scan(&project.Id, &project.Name) failed to copy the current row's columns into the shared.Project fields. This is a column/type mismatch or a NULL value being scanned into a non-nullable Go type; the handler responds with 500 and the scan error text.","triggerScenarios":"GET/POST list-projects with at least one row in projects where the id or name column is NULL, or where the column type doesn't fit the destination (e.g. non-text in name), or the SELECT column order/count was changed without updating Scan.","commonSituations":"Manual inserts or imports that left name NULL; schema changed (column type altered or reordered) while the hardcoded SELECT/Scan stayed the same; using a driver that returns an unusual type for the column.","solutions":["Read the appended error: 'converting NULL to string is unsupported' means a NULL id/name row exists — clean or backfill the bad row.","Declare destinations as sql.NullString (or pointers) if NULLs are legitimate.","Keep the SELECT column list and Scan argument order/count in sync after any schema change.","Validate that shared.Project.Id/Name types match the actual column types."],"exampleFix":"// before\nvar project shared.Project\nerr := rows.Scan(&project.Id, &project.Name)\n// after\nvar name sql.NullString\nerr := rows.Scan(&project.Id, &name)\nproject.Name = name.String","handlingStrategy":"validation","validationCode":"SELECT id, name FROM projects WHERE org_id = $1 AND id IS NOT NULL AND name IS NOT NULL","typeGuard":"func scanProject(row *sql.Row) (shared.Project, error) {\n\tvar p shared.Project\n\tvar name sql.NullString\n\tif err := row.Scan(&p.Id, &name); err != nil {\n\t\treturn p, err\n\t}\n\tp.Name = name.String\n\treturn p, nil\n}","tryCatchPattern":null,"preventionTips":["Make NOT NULL constraints on projects.id and projects.name so bad rows can't exist.","Use COALESCE(name, '') or sql.NullString when NULLs are possible.","Run a data-quality check after manual imports or migrations.","Keep SELECT column order and Scan args in sync; add a row-scanning unit test with fixtures."],"tags":["database","sql","scan","null","http-500"],"backgroundTag":"sql-scan-type-mismatch","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"}