plandex-ai/plandex · error

error updating plan active branches: %v

Error message

error updating plan active branches: %v

What it means

IncActiveBranches increments (or decrements, via a negative inc) plans.active_branches using the required *sqlx.Tx. This wrapper fires when that UPDATE fails. Since it always runs inside a transaction (called by CreateBranch and transactional anonymous blocks), the most common cause is executing against a transaction that was already aborted, or a connection failure during commit-heavy operations.

Source

Thrown at app/server/db/plan_helpers.go:293

	var err error
	if tx == nil {
		_, err = Conn.Exec("UPDATE plans SET name = $1 WHERE id = $2", name, planId)
	} else {
		_, err = tx.Exec("UPDATE plans SET name = $1 WHERE id = $2", name, planId)
	}

	if err != nil {
		return fmt.Errorf("error renaming plan: %v", err)
	}

	return nil
}

func IncActiveBranches(planId string, inc int, tx *sqlx.Tx) error {
	_, err := tx.Exec("UPDATE plans SET active_branches = active_branches + $1 WHERE id = $2", inc, planId)

	if err != nil {
		return fmt.Errorf("error updating plan active branches: %v", err)
	}

	return nil
}

func IncNumNonDraftPlans(userId string, tx *sqlx.Tx) error {
	_, err := tx.Exec("UPDATE users SET num_non_draft_plans = num_non_draft_plans + 1 WHERE id = $1", userId)

	if err != nil {
		return fmt.Errorf("error updating user num_non_draft_plans: %v", err)
	}

	return nil
}

func StoreDescription(description *ConvoMessageDescription) error {
	descriptionsDir := getPlanDescriptionsDir(description.OrgId, description.PlanId)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Ensure every error in the surrounding transaction triggers tx.Rollback() before any further statement — an aborted tx makes this UPDATE fail
  2. Check the inner error for connection issues; if the pool is exhausted, close transactions faster (avoid holding them across I/O)
  3. Verify inc values keep active_branches >= 0 if the column has a non-negative CHECK constraint
  4. Confirm the plans row for planId exists inside the tx before incrementing

Example fix

// before
_, err := tx.Exec("UPDATE plans SET active_branches = active_branches + $1 WHERE id = $2", inc, planId)
if err != nil {
    return fmt.Errorf("error updating plan active branches: %v", err)
}
// after
_, err := tx.Exec("UPDATE plans SET active_branches = active_branches + $1 WHERE id = $2", inc, planId)
if err != nil {
    tx.Rollback()
    return fmt.Errorf("error updating plan active branches: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

var exists bool
if err := Conn.Get(&exists, "SELECT EXISTS(SELECT 1 FROM plans WHERE id = $1)", planId); err != nil || !exists {
    return fmt.Errorf("plan %s not found", planId)
}

Type guard

func txUsable(tx *sqlx.Tx) bool {
    return tx != nil
}

Try / catch

err := IncActiveBranches(planId, 1, tx)
if err != nil {
    _ = tx.Rollback()
    return fmt.Errorf("branch creation failed: %w", err)
}
if err := tx.Commit(); err != nil {
    return fmt.Errorf("commit failed: %w", err)
}

Prevention

When it happens

Trigger: Calling IncActiveBranches with an already-rolled-back or committed tx; DB connection failure inside the transaction; concurrent branch creation causing lock contention; constraint/trigger failure on the plans table during the increment.

Common situations: CreateBranch flows where a prior statement in the tx failed and the tx was not rolled back before this call; pool exhaustion while holding a tx open too long; passing a negative inc that drives active_branches negative when the column has a CHECK constraint.

Related errors


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