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

  1. Check server logs for the raw driver error printed alongside this message and fix the underlying DB connectivity issue (pool limits, restarts, network).
  2. Verify the Postgres driver in use (lib/pq / pgx stdlib) is up to date and properly implements RowsAffected.
  3. Use a health-checked connection pool (ping, idle timeouts) so dead connections are recycled before Exec.
  4. 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

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


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/3ff0f9999fafce72. Report an issue: GitHub.