{"record":{"id":"dc70258f5b717505","repo":"plandex-ai/plandex","slug":"error-deleting-model-pack-v","errorCode":null,"errorMessage":"error deleting model pack: %v","messagePattern":"error deleting model pack: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/models.go","lineNumber":269,"sourceCode":"\n\treturn modelPacks, nil\n}\n\nfunc ListModelPacksForNames(orgId string, names []string) ([]*ModelPack, error) {\n\tvar modelPacks []*ModelPack\n\tquery := `SELECT * FROM model_sets WHERE org_id = $1 AND name = ANY($2)`\n\terr := Conn.Select(&modelPacks, query, orgId, names)\n\treturn modelPacks, err\n}\n\nfunc DeleteModelPacks(tx *sqlx.Tx, orgId string, ids []string) error {\n\tif tx == nil {\n\t\treturn fmt.Errorf(\"tx is nil\")\n\t}\n\t_, err := tx.Exec(`DELETE FROM model_sets WHERE org_id = $1 AND id = ANY($2)`, orgId, pq.Array(ids))\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting model pack: %v\", err)\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":251,"sourceCodeEnd":274,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/models.go#L251-L274","documentation":"DeleteModelPacks wraps a failure of the batched DELETE on model_sets (org_id + id ANY($2)). Deleting zero matching rows is not an error; this fires only when the statement execution fails, e.g. FK constraints from tables referencing model_sets, permissions, or an aborted transaction.","triggerScenarios":"tx already aborted by an earlier failed statement; model rows referencing the model_set block the DELETE with a foreign-key violation; missing DELETE grant; model_sets table missing.","commonSituations":"Dependent custom models still reference the pack; shared production DB where app role lacks DELETE; caller reusing a failed tx in a multi-step handler.","solutions":["Inspect the wrapped pq error code: 23503 means FK violation — delete or cascade dependent rows first","If the tx is aborted, roll back and retry in a fresh tx","Grant DELETE on model_sets to the app role","Confirm model_sets exists via migrations","Retry once on transient connection/deadlock errors"],"exampleFix":"// before\n_, err := tx.Exec(`DELETE FROM model_sets WHERE org_id = $1 AND id = ANY($2)`, orgId, pq.Array(ids))\n// after\n_, err := tx.Exec(`DELETE FROM custom_models WHERE model_set_id = ANY($1)`, pq.Array(ids)) // clear dependents\nif err != nil { return err }\n_, err = tx.Exec(`DELETE FROM model_sets WHERE org_id = $1 AND id = ANY($2)`, orgId, pq.Array(ids))","handlingStrategy":"try-catch","validationCode":"// before deleting, ensure no dependents\nvar refs int\nerr := tx.Get(&refs, `SELECT count(*) FROM custom_models WHERE model_set_id = ANY($1)`, pq.Array(ids))\nif err == nil && refs > 0 { return errors.New(\"model pack still referenced by custom models\") }","typeGuard":"func isPgCode(err error, code string) bool {\n    var pgErr *pgconn.PgError\n    return errors.As(err, &pgErr) && pgErr.Code == code\n}","tryCatchPattern":"if err := db.DeleteModelPacks(tx, orgId, ids); err != nil {\n    if isPgCode(err, \"23503\") { return fmt.Errorf(\"pack referenced by other rows: %w\", err) }\n    return err\n}","preventionTips":["Delete or cascade dependent rows before removing model_sets","Never reuse a tx after a failed statement — roll back and start over","Grant DELETE on model_sets to the application role","Add ON DELETE CASCADE where dependents should follow the pack","Retry deadlocks (40P01) at the transaction level"],"tags":["database","postgres","sqlx","foreign-key"],"backgroundTag":"sql-delete-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}