gotify/server · error

failed to elevate session: %v

Error message

failed to elevate session: %v

What it means

handleElevationCallback (api/oidc.go:269) returns HTTP 500 'failed to elevate session: %v' when a.DB.UpdateClientElevatedUntil(client.ID, &elevatedUntil) errors after the client was found and ownership verified. The client lookup succeeded but persisting the new elevated-until timestamp failed.

Source

Thrown at api/oidc.go:269

		w.Header().Set("Location", "../../")
		w.WriteHeader(http.StatusTemporaryRedirect)
	}
	return gin.WrapF(rp.CodeExchangeHandler(rp.UserinfoCallback(callback), a.Provider))
}

func (a *OIDCAPI) handleElevationCallback(w http.ResponseWriter, elevate *pendingElevation, user *model.User) {
	client, err := a.DB.GetClientByID(elevate.ClientID)
	if err != nil {
		http.Error(w, fmt.Sprintf("database error: %v", err), http.StatusInternalServerError)
		return
	}
	if client == nil || client.UserID != user.ID {
		http.Error(w, "client not found", http.StatusNotFound)
		return
	}
	elevatedUntil := time.Now().Add(time.Duration(elevate.DurationSeconds) * time.Second)
	if err := a.DB.UpdateClientElevatedUntil(client.ID, &elevatedUntil); err != nil {
		http.Error(w, fmt.Sprintf("failed to elevate session: %v", err), http.StatusInternalServerError)
		return
	}

	// The UI rechecks the authentication when the tab is closed.
	w.WriteHeader(http.StatusOK)
	w.Header().Add("content-type", "text/html")
	io.WriteString(w, `<!DOCTYPE html>
<html lang="en">
<head>
  <title>Gotify Session Elevation</title>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
</head>
<body>
  <h1 style="text-align:center">Gotify session elevation successful. Close this tab to continue.</h1>
  <script>window.close();</script>
</body>
</html>`)

View on GitHub (pinned to 14bfc25627)

Solutions

  1. Check the wrapped error and database server logs; verify connectivity and that the DB accepts writes
  2. Confirm the DB user has UPDATE permission on the clients table and migrations are current
  3. Retry the elevation flow (with a fresh state) once the database is writable
  4. For SQLite lock errors, ensure no other process holds the DB and consider WAL mode
  5. Rule out read-only replica routing or disk-space/quota issues
Defensive patterns

Strategy: retry

Validate before calling

// Before the elevation round-trip, verify the DB accepts writes on clients
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
if err := db.PingContext(ctx); err != nil {
    return err
}
// optionally a probe write/transaction to catch read-only replicas early

Try / catch

err := db.UpdateClientElevatedUntil(clientID, &elevatedUntil)
if err != nil {
    if isTransient(err) { // deadlock, bad conn, timeout, lock
        return retryWithBackoff(func() error {
            return db.UpdateClientElevatedUntil(clientID, &elevatedUntil)
        })
    }
    return fmt.Errorf("update elevated_until: %w", err)
}

Prevention

When it happens

Trigger: UpdateClientElevatedUntil fails during the elevation callback: database connection dropped between the read and the write, write timeout, read-only replica/transaction, constraint or schema error, or disk-full on the DB server.

Common situations: Remote Postgres briefly unavailable or failing over; DB user lacking UPDATE privilege on the clients table; migrations missing a column used by the update; SQLite database locked by another process; storage quota exhausted.

Related errors


AI-assisted analysis of gotify/server@14bfc25627 (2026-09-05). Data as JSON: /api/errors/3585d6dd318f0d20. Report an issue: GitHub.