{"record":{"id":"2c470a8d170a323b","repo":"plandex-ai/plandex","slug":"failed-to-import-custom-models-providers-model-pac","errorCode":null,"errorMessage":"Failed to import custom models/providers/model packs: ","messagePattern":"Failed to import custom models/providers/model packs: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/models.go","lineNumber":332,"sourceCode":"\n\t\tif len(toDeleteCustomProviderIds) > 0 {\n\t\t\tif err := db.DeleteCustomProviders(tx, auth.OrgId, toDeleteCustomProviderIds); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error deleting custom providers: %w\", err)\n\t\t\t}\n\t\t}\n\n\t\tif len(toDeleteModelPackIds) > 0 {\n\t\t\tif err := db.DeleteModelPacks(tx, auth.OrgId, toDeleteModelPackIds); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error deleting model packs: %w\", err)\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tif err != nil {\n\t\tlog.Printf(\"Error: %v\\n\", err)\n\t\thttp.Error(w, \"Failed to import custom models/providers/model packs: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.WriteHeader(http.StatusOK)\n\n\tlog.Println(\"Successfully imported custom models/providers/model packs\")\n}\n\nfunc GetCustomModelHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for GetCustomModelHandler\")\n\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tid := mux.Vars(r)[\"modelId\"]\n","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/models.go#L314-L350","documentation":"Thrown at models.go:332 when the db.WithTx transaction that upserts/deletes custom models, providers, and model packs fails or the context is canceled. The transaction wraps UpsertCustomModel, UpsertCustomProvider, UpsertModelPack, DeleteCustomModels, DeleteCustomProviders, and DeleteModelPacks; any error rolls back all changes. The client sees a 500 with the wrapped DB error appended.","triggerScenarios":"POST to the upsert custom models endpoint passes all validation, but the transaction fails: unique constraint violation (duplicate model id/name inserted concurrently), FK violation (deleting a provider still referenced), DB connection lost mid-transaction, or r.Context() canceled (client disconnected / timeout).","commonSituations":"Concurrent upserts from two clients causing constraint conflicts; deleting a provider while another custom model still references it in the DB; long transactions hitting statement timeouts; client closing the connection while the import runs.","solutions":["Read the server log 'Error: ...' line for the wrapped root cause (constraint, FK, connection)","Check for unique-constraint or foreign-key conflicts implied by the message and fix the payload ordering (create referenced providers/models before packs)","Retry the request; ensure the client does not abort mid-request","Check DB health, locks, and statement timeouts if imports are large"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// 500 during tx — retry whole upsert with backoff; tx rollback means no partial state\nif resp.StatusCode == 500 && strings.Contains(bodyText, \"Failed to import custom models/providers/model packs\") {\n    return backoffRetry(func() error { return upsert(input) }, 3)\n}","preventionTips":["Serialize upserts per org to avoid concurrent constraint conflicts","Keep the HTTP client alive for the full request duration (long timeouts)","Ensure referenced providers/models are imported before packs to satisfy FKs","Monitor DB locks and statement timeouts during large imports"],"tags":["database","transaction","http-500"],"backgroundTag":"transaction-rolled-back","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"}