plandex-ai/plandex · error
Error getting rows affected:
Error message
Error getting rows affected:
What it means
In DeletePlanHandler (app/server/handlers/plans_crud.go:244), the DELETE statement against the plans table succeeded, but calling res.RowsAffected() on the driver's result returned an error. This is a database/sql driver-level failure: the driver could not report how many rows the DELETE removed. It is almost always a driver/DB connectivity or capability issue, not an application-logic bug.
Source
Thrown at app/server/handlers/plans_crud.go:244
if plan.OwnerId != auth.User.Id {
log.Println("Only the plan owner can delete a plan")
http.Error(w, "Only the plan owner can delete a plan", http.StatusForbidden)
return
}
res, err := db.Conn.Exec("DELETE FROM plans WHERE id = $1", planId)
if err != nil {
log.Printf("Error deleting plan: %v\n", err)
http.Error(w, "Error deleting plan: "+err.Error(), http.StatusInternalServerError)
return
}
rowsAffected, err := res.RowsAffected()
if err != nil {
log.Printf("Error getting rows affected: %v\n", err)
http.Error(w, "Error getting rows affected: "+err.Error(), http.StatusInternalServerError)
return
}
if rowsAffected == 0 {
log.Println("Plan not found")
http.Error(w, "Not found", http.StatusNotFound)
return
}
err = db.DeletePlanDir(auth.OrgId, planId)
if err != nil {
log.Printf("Error deleting plan dir: %v\n", err)
http.Error(w, "Error deleting plan dir: "+err.Error(), http.StatusInternalServerError)
return
}
log.Println("Successfully deleted plan", planId)View on GitHub (pinned to e2d772072e)
Solutions
- Check server logs for the raw driver error printed alongside this message and fix the underlying DB connectivity issue (pool limits, restarts, network).
- Verify the Postgres driver in use (lib/pq / pgx stdlib) is up to date and properly implements RowsAffected.
- Use a health-checked connection pool (ping, idle timeouts) so dead connections are recycled before Exec.
- If the DB row was deleted but the response was 500, treat the delete as idempotent: retrying will return 404 'Not found', not duplicate deletion.
Example fix
// before
res, err := db.Conn.Exec("DELETE FROM plans WHERE id = $1", planId)
// after
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
res, err := db.Conn.ExecContext(ctx, "DELETE FROM plans WHERE id = $1", planId) Defensive patterns
Strategy: try-catch
Validate before calling
if err := db.Conn.PingContext(ctx); err != nil {
// DB connection unhealthy — do not attempt the delete
} Type guard
func isDriverResultErr(err error) bool {
var pgErr *pgconn.PgError
return errors.As(err, &pgErr)
} Try / catch
res, err := db.Conn.ExecContext(ctx, "DELETE FROM plans WHERE id = $1", planId)
if err != nil { return }
rowsAffected, err := res.RowsAffected()
if err != nil {
log.Printf("rows affected unavailable, treating as success: %v", err)
return // row delete already committed; do not fail the request
} Prevention
- Ping the DB or use health-checked pooled connections before writes.
- Set ExecContext timeouts so dead connections fail fast.
- Keep the Postgres driver updated.
- Treat the delete as committed once Exec succeeds; never re-delete on RowsAffected failure without checking existence.
When it happens
Trigger: DELETE FROM plans WHERE id = $1 executes without error via db.Conn.Exec, but res.RowsAffected() fails — e.g. the Postgres connection dropped mid-response, the driver (lib/pq or pgx stdlib) cannot retrieve the command tag, or a non-supporting driver wrapper returns an error from RowsAffected.
Common situations: Connection pool exhaustion or a DB restart between Exec and RowsAffected; using a driver or transaction wrapper that does not implement RowsAffected; network interruption in long-lived server processes.
Related errors
- error getting current plan state params: %v
- error getting contexts: %v
- error validating project
- error validating plan membership
- Error validating org membership:
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/3ff0f9999fafce72.
Report an issue: GitHub.