plandex-ai/plandex · error
error storing default plan config: %v
Error message
error storing default plan config: %v
What it means
StoreDefaultPlanConfig wraps a failure of `UPDATE users SET default_plan_config = $1 WHERE id = $2` executed on the caller-supplied transaction (tx.Exec) with this message. Because it runs on a tx, this error typically also aborts the surrounding transaction via WithTx.
Source
Thrown at app/server/db/plan_config_helpers.go:61
var config shared.PlanConfig
err := Conn.Get(&config, query, userId)
if err != nil {
return nil, fmt.Errorf("error getting default plan config: %v", err)
}
return &config, nil
}
func StoreDefaultPlanConfig(userId string, config *shared.PlanConfig, tx *sqlx.Tx) error {
query := `
UPDATE users SET default_plan_config = $1 WHERE id = $2
`
_, err := tx.Exec(query, config, userId)
if err != nil {
return fmt.Errorf("error storing default plan config: %v", err)
}
return nil
}
View on GitHub (pinned to e2d772072e)
Solutions
- Ensure a valid, non-nil, still-open *sqlx.Tx is passed and that no earlier statement in the transaction already failed
- Inspect the wrapped cause: connection errors mean check Postgres health/DATABASE_URL and retry the whole transaction
- Confirm migrations define users.default_plan_config
- If the userId may not exist, check RowsAffected after Exec — a zero-row update succeeds silently and is a separate bug from this error
Example fix
// before
err = StoreDefaultPlanConfig(userId, config, tx) // tx may be dead after earlier error
// after
if err := doOtherWork(tx); err != nil {
return err // abort early so tx isn't reused in a broken state
}
if err := StoreDefaultPlanConfig(userId, config, tx); err != nil {
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
if tx == nil {
return errors.New("StoreDefaultPlanConfig requires an active transaction")
}
var exists bool
Conn.Get(&exists, "SELECT EXISTS(SELECT 1 FROM users WHERE id=$1)", userId) Try / catch
err := WithTx(ctx, "store default plan config", func(tx *sqlx.Tx) error {
if err := StoreDefaultPlanConfig(userId, config, tx); err != nil {
return fmt.Errorf("store default plan config for %s: %w", userId, err)
}
return nil
})
if err != nil { return err } // tx rolled back safely Prevention
- Always invoke via WithTx so tx lifetime/rollback is managed
- Return immediately on the first error inside a transaction; never reuse a failed tx
- Respect ctx cancellation — canceling the context aborts the tx mid-statement
- Check RowsAffected to catch zero-row updates on unknown userIds
When it happens
Trigger: Called with a nil or already-committed/rolled-back *sqlx.Tx (nil pointer dereference or 'tx has been committed' error), the users row doesn't exist (silent zero-row update — not this error), DB connection lost, or the PlanConfig cannot be driver-encoded.
Common situations: Transaction context canceled mid-flight (WithTx with a canceled ctx); caller reuses a tx after an earlier error; connection-pool exhaustion; schema drift removing default_plan_config.
Related errors
- error adding org user: %v
- error storing plan config: %v
- error getting default plan config: %v
- error adding plan context tokens: %v
- error accepting invite: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/63512427ae593475.
Report an issue: GitHub.