plandex-ai/plandex · error
error deleting custom providers: %v
Error message
error deleting custom providers: %v
What it means
DeleteCustomProviders wraps any failure of the batched DELETE on custom_providers (scoped by org_id and id ANY($2)) with this message. Zero rows deleted is not an error; this only fires when the SQL execution itself fails. The wrapped error is the lib/pq driver or Postgres error.
Source
Thrown at app/server/db/models.go:189
var providers []*CustomProvider
err := Conn.Select(&providers, `SELECT * FROM custom_providers WHERE org_id = $1 ORDER BY name`, orgId)
return providers, err
}
func ListCustomProvidersForNames(orgId string, names []string) ([]*CustomProvider, error) {
var providers []*CustomProvider
query := `SELECT * FROM custom_providers WHERE org_id = $1 AND name = ANY($2) ORDER BY name`
err := Conn.Select(&providers, query, orgId, pq.Array(names))
return providers, err
}
func DeleteCustomProviders(tx *sqlx.Tx, orgId string, ids []string) error {
if tx == nil {
return fmt.Errorf("tx is nil")
}
_, err := tx.Exec(`DELETE FROM custom_providers WHERE org_id = $1 AND id = ANY($2)`, orgId, pq.Array(ids))
if err != nil {
return fmt.Errorf("error deleting custom providers: %v", err)
}
return nil
}
func UpsertModelPack(tx *sqlx.Tx, mp *ModelPack) error {
if tx == nil {
return fmt.Errorf("tx is nil")
}
const q = `
INSERT INTO model_sets (
org_id, name, description,
planner, coder, plan_summary,
builder, whole_file_builder, namer,
commit_msg, exec_status, context_loader
)
VALUES (
$1,$2,$3,
$4,$5,$6,View on GitHub (pinned to e2d772072e)
Solutions
- Read the wrapped error code (pq/pgerror) and verify the table and constraints (\d custom_providers)
- If the transaction is aborted from a prior failure, roll back and start a new tx
- Grant DELETE on custom_providers to the application role
- Remove/cascade dependent references before deleting providers
- Check logs for deadlock/timeout and retry the whole transaction
Example fix
// before
_, err := tx.Exec(`DELETE FROM custom_providers WHERE org_id = $1 AND id = ANY($2)`, orgId, pq.Array(ids))
if err != nil { return fmt.Errorf("error deleting custom providers: %v", err) }
// after
_, err := tx.Exec(`DELETE FROM custom_providers cp USING models m WHERE cp.id = m.provider_id AND ...`) // delete dependents first
_, err = tx.Exec(`DELETE FROM custom_providers WHERE org_id = $1 AND id = ANY($2)`, orgId, pq.Array(ids)) Defensive patterns
Strategy: try-catch
Validate before calling
func validateDeleteCustomProviders(tx *sqlx.Tx, orgId string, ids []string) error {
if tx == nil { return errors.New("tx is nil") }
if len(ids) == 0 { return errors.New("no provider ids given") }
return nil
} Type guard
func isForeignKeyViolation(err error) bool {
var pgErr *pgconn.PgError
return errors.As(err, &pgErr) && pgErr.Code == "23503"
} Try / catch
if err := db.DeleteCustomProviders(tx, orgId, ids); err != nil {
if isForeignKeyViolation(err) { return fmt.Errorf("providers still referenced: %w", err) }
return err
} Prevention
- Check for dependent models before deleting providers
- Roll back and retry in a fresh tx after any prior statement failure
- Verify custom_providers exists via migrations in every environment
- Ensure the DB role has DELETE privileges
- Use pq.Array consistently for id arrays
When it happens
Trigger: Dead/aborted transaction passed to DeleteCustomProviders; FK constraint referencing custom_providers rows; missing DELETE privilege; custom_providers table absent due to skipped migrations; malformed ids for pq.Array.
Common situations: Staging DB without latest migrations; production role without DELETE grants; a long-running tx hit a deadlock or statement_timeout; custom providers still referenced by models.
Related errors
- error deleting custom models: %v
- error committing transaction: %v
- error fetching model packs: %v
- error deleting model pack: %v
- error getting orgs for user: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/9192def8e3ef44c2.
Report an issue: GitHub.