{"record":{"id":"93afee49c6ed0e3c","repo":"plandex-ai/plandex","slug":"error-deleting-plans-v","errorCode":null,"errorMessage":"error deleting plans: %v","messagePattern":"error deleting plans: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/plan_helpers.go","lineNumber":403,"sourceCode":"\n\tfor i := 0; i < len(ids); i++ {\n\t\terr := <-errCh\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error deleting draft plan dir: %v\", err)\n\t\t}\n\t}\n\n\tif len(ids) > 0 {\n\t\tlog.Println(\"Deleted\", len(ids), \"draft plans\")\n\t}\n\n\treturn nil\n}\n\nfunc DeleteOwnerPlans(orgId, projectId, userId string) error {\n\tres, err := Conn.Query(\"DELETE FROM plans WHERE project_id = $1 AND owner_id = $2 RETURNING id;\", projectId, userId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting plans: %v\", err)\n\t}\n\n\tdefer res.Close()\n\n\t// get ids\n\tvar ids []string\n\n\tfor res.Next() {\n\t\tvar id string\n\t\terr := res.Scan(&id)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error scanning deleted draft plan id: %v\", err)\n\t\t}\n\t\tids = append(ids, id)\n\t}\n\n\terrCh := make(chan error, len(ids))\n\tfor _, planId := range ids {","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/plan_helpers.go#L385-L421","documentation":"DeleteOwnerPlans deletes ALL plans owned by a user in a project (not just drafts) and collects their ids via RETURNING. This error wraps a failure of the DELETE query itself, meaning the database could not execute the statement.","triggerScenarios":"Conn.Query(\"DELETE FROM plans WHERE project_id = $1 AND owner_id = $2 RETURNING id;\", ...) fails: dead DB connection, schema mismatch, permission denied on the plans table for the app's DB role, or statement timeout.","commonSituations":"DB role lacking DELETE privilege after a security hardening change; connection pool exhaustion; migration drift removing the owner_id column; network partition between app and Postgres.","solutions":["Check the wrapped driver error for the exact cause","Verify the app's DB role has DELETE privilege on plans","Confirm schema contains project_id/owner_id columns (run migrations)","Check connection pool health and timeouts"],"exampleFix":"// before\nif err != nil {\n    return fmt.Errorf(\"error deleting plans: %v\", err)\n}\n// after\nif err != nil {\n    return fmt.Errorf(\"error deleting plans: %w\", err)\n}","handlingStrategy":"retry","validationCode":"var hasDelete bool\nerr := db.Get(&hasDelete, \"SELECT has_table_privilege('plans', 'DELETE')\")\nif err != nil || !hasDelete {\n    return fmt.Errorf(\"app role lacks DELETE on plans\")\n}","typeGuard":null,"tryCatchPattern":"if err := DeleteOwnerPlans(orgId, projectId, userId); err != nil {\n    var pqErr *pq.Error\n    if errors.As(err, &pqErr) && pqErr.Code == \"42501\" {\n        // permission denied: grant DELETE or fix role\n    }\n    return err\n}","preventionTips":["Grant the app DB role DELETE on plans in migration scripts","Run migrations before deploy","Retry on driver.ErrBadConn and net errors","Monitor DB connectivity and pool limits"],"tags":["database","postgres","sql","delete"],"backgroundTag":"database-query-failed","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"}