{"record":{"id":"b0e5ed7fc673b0c9","repo":"gotify/server","slug":"failed-to-create-client-v","errorCode":null,"errorMessage":"failed to create client: %v","messagePattern":"failed to create client: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"api/oidc.go","lineNumber":244,"sourceCode":"\t\tuser, status, err := a.resolveUser(tokens.IDTokenClaims, info)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), status)\n\t\t\treturn\n\t\t}\n\t\tsession, ok := a.popPendingSession(state)\n\t\tif !ok {\n\t\t\thttp.Error(w, \"unknown or expired state\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tif session.Elevate != nil {\n\t\t\ta.handleElevationCallback(w, session.Elevate, user)\n\t\t\treturn\n\t\t}\n\n\t\tclient, err := a.createClient(session.ClientName, user.ID)\n\t\tif err != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"failed to create client: %v\", err), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tauth.SetCookie(w, client.Token, auth.CookieMaxAge, a.SecureCookie)\n\t\t// A reverse proxy may have already stripped a url prefix from the URL\n\t\t// without us knowing, we have to make a relative redirect.\n\t\t// We cannot use http.Redirect as this normalizes the Path with r.URL.\n\t\tw.Header().Set(\"Location\", \"../../\")\n\t\tw.WriteHeader(http.StatusTemporaryRedirect)\n\t}\n\treturn gin.WrapF(rp.CodeExchangeHandler(rp.UserinfoCallback(callback), a.Provider))\n}\n\nfunc (a *OIDCAPI) handleElevationCallback(w http.ResponseWriter, elevate *pendingElevation, user *model.User) {\n\tclient, err := a.DB.GetClientByID(elevate.ClientID)\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"database error: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/gotify/server/blob/14bfc256276775c425f988d621dccfe705de18ac/api/oidc.go#L226-L262","documentation":"After a successful OIDC callback, api/oidc.go:244 wraps any error from a.createClient(session.ClientName, user.ID) into an HTTP 500 'failed to create client: %v'. createClient persists a new client record (with token) for the authenticated user; failure means the client could not be stored even though OIDC authentication itself succeeded.","triggerScenarios":"createClient fails while handling the provider callback: database unavailable or returning an error on insert, unique/name constraint violated by the requested client name, DB schema mismatch after an upgrade, or disk/storage errors during the insert.","commonSituations":"Postgres/SQLite down or connection pool exhausted during login; duplicate client name from retrying the login with the same name; migration not applied so the clients table lacks a column; database read-only or out of disk space.","solutions":["Check the wrapped inner error in the response/log and verify database connectivity and health","Confirm database migrations are up to date for the gotify version","Retry the OIDC login once the database is healthy; the state was consumed, so start a new login","If a duplicate-name constraint is the cause, retry with a different client name","Inspect DB logs for lock/permission/disk errors during the insert"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before initiating the login that will create a client, verify the DB is reachable\nif err := db.Ping(); err != nil {\n    return fmt.Errorf(\"database unavailable, fix before login: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"client, err := createClient(name, userID)\nif err != nil {\n    log.Printf(\"client creation failed: %v\", err) // keep the wrapped cause\n    if errors.Is(err, sql.ErrNoRows) || isConstraintViolation(err) {\n        return retryWithNewName(name) // duplicate/conflict case\n    }\n    return retryWithBackoff(err) // transient DB error\n}","preventionTips":["Monitor database health before/at login time","Keep migrations applied when upgrading gotify","Avoid retrying logins with an identical client name if name conflicts are possible","Alert on insert failures in the clients table","Ensure adequate disk space and connection-pool headroom"],"tags":["database","oidc","http-500","client-creation"],"backgroundTag":"database-insert-failed","analyzedSha":"14bfc256276775c425f988d621dccfe705de18ac","analyzedAt":"2026-09-05T12:52:36.781Z","contentChangedAt":"2026-09-05T12:52:36.781Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}