April 20, 2026 • Version: 2026.2.17 - 2026.2.23

[Web-UI-Sitzungszeitüberschreitung: HTTP 401 nach Inaktivität] - Web UI Session Timeout: HTTP 401 After Inactivity in OpenClaw Control UI

Die OpenClaw Control UI gibt nach 10-15 Minuten Inaktivität aufgrund des Ablaufs der WebSocket-Sitzung ohne automatische Token-Re-Authentifizierung beim erneuten Verbinden den HTTP 401 Invalid Authentication-Fehler zurück.

🔍 Symptome

Primäre Manifestation

Nach ungefähr 10-15 Minuten Inaktivität des Browser-Tabs führt ein Versuch, eine Nachricht über die OpenClaw Control UI zu senden, zu einem Authentifizierungsfehler:

HTTP 401: Invalid Authentication
Status: 401 Unauthorized
X-Error-Code: INVALID_AUTH_TOKEN

Reproduktionssequenz

  1. Navigieren Sie zu http://127.0.0.1:18789/ im Browser
  2. Authentifizieren Sie sich mit dem Gateway-Token (wird automatisch in localStorage gespeichert)
  3. Senden Sie 2-3 Nachrichten erfolgreich über die WebSocket-Verbindung
  4. Lassen Sie den Tab 10-15 Minuten inaktiv (schließen Sie ihn nicht)
  5. Kehren Sie zum Tab zurück und versuchen Sie, eine neue Nachricht zu senden
  6. Beobachten Sie den 401-Fehler in der UI und der Netzwerkkonsole

Netzwerkaktivität während des Fehlers

Die Untersuchung der Browser DevTools (F12 → Netzwerk-Tab) zeigt:

# WebSocket-Verbindungsstatus
Connection State: CONNECTING → CLOSED
Close Code: 1006 (Abnormal Closure)
Close Reason: "Session expired"

# Nachfolgende HTTP-Anfragen
POST /api/v1/messages
  Authorization: Bearer [expired_session_token]
  Response: 401 Unauthorized
  Body: {"error": "INVALID_AUTH_TOKEN", "message": "Session has expired"}

Konsolenausgabe

[OpenClaw] Connection lost, attempting reconnect...
[OpenClaw] WebSocket reconnected
[OpenClaw] Authentication failed: 401
[OpenClaw] Token validation error: Token not found in session store

Unterscheidungsmerkmale

BedingungVerhalten
Tab inaktiv < 10 Min.Normaler Betrieb
Tab inaktiv > 10-15 Min.401-Fehler beim Nachrichtensenden
F5 / SeitenaktualisierungSofortige Lösung
Browser-Konsole leerenGleicher 401-Fehler bleibt bestehen

🧠 Ursache

Architektonische Übersicht

Die OpenClaw Control UI verwendet eine Dual-Transport-Architektur:

┌─────────────────────────────────────────────────────────────┐
│                      Browser Client                          │
│  ┌──────────────┐    ┌────────────────┐    ┌─────────────┐  │
│  │  localStorage │    │  WebSocket Conn │    │  HTTP Client │  │
│  │  (Auth Token) │───▶│  (Message Bus)  │◀───│  (REST API)  │  │
│  └──────────────┘    └────────────────┘    └─────────────┘  │
└────────────────────────────┬────────────────────────────────┘
                             │
                     ┌───────▼───────┐
                     │ OpenClaw Core  │
                     │   (Gateway)    │
                     └────────────────┘

Fehlersequenz

  1. Erstauthentifizierung: Der Benutzer authentifiziert sich; JWT wird als openclaw_auth_token in localStorage gespeichert
  2. Sitzungserstellung: Gateway erstellt serverseitige Sitzung, die mit der WebSocket-Verbindungs-ID verknüpft ist
  3. Aktive Phase: Nachrichten fließen korrekt über den etablierten WebSocket-Kanal
  4. Timeout-Auslöser: Nach ~10-15 Minuten läuft die serverseitige Sitzung wegen Inaktivitäts-Timeout ab
  5. WebSocket-Schließung: Server schließt WebSocket mit Code 1006 oder sendet Session expired-Frame
  6. Stille Wiederverbindung: Client versucht Reconnect, nimmt aber KEIN Auth-Token in den Wiederverbindungs-Handshake auf
  7. Auth-Fehler: Neue WebSocket-Verbindung wird mit 401 abgelehnt, da der Sitzungsspeicher leer ist

Codepfad-Analyse

Der Fehler befindet sich in der Wiederverbindungslogik des Clients:

// Hypothetischer problematischer Code in web-ui/src/services/connection.ts

class ConnectionManager {
  async reconnect() {
    // ❌ FEHLER: Ruft Token nicht aus localStorage ab
    const ws = new WebSocket(this.gatewayUrl);
    
    ws.onopen = () => {
      // Fehlt: this.authenticate();
    };
  }
  
  // Korrekte Implementierung würde beinhalten:
  async authenticate() {
    const token = localStorage.getItem('openclaw_auth_token');
    this.ws.send(JSON.stringify({
      type: 'AUTH',
      token: token  // ← Dieser Schritt fehlt bei reconnect
    }));
  }
}

Sitzungsverwaltungs-Diskrepanz

Das Problem wird durch eine Versionsabweichung verschärft:

CLI Version:     2026.2.23
Browser Version: 2026.2.17

Dies deutet darauf hin, dass das Gateway möglicherweise separat von den eingebetteten Web-UI-Assets aktualisiert wurde, was dazu führen kann, dass die Sitzungsvalidierungslogik zwischen Server und Client divergiert.

Umgebungsbezogene Faktoren

FaktorAuswirkung
GATEWAY_SESSION_TIMEOUTStandard 600 Sekunden (10 Min.)
GATEWAY_WEBSOCKET_PING_INTERVALMöglicherweise nicht konfiguriert, verursacht TCP-Keepalive-Lücken
Browser-Tab-HintergrundungBrowser können WebSocket in Hintergrund-Tabs drosseln
macOS-EnergieverwaltungKann Tab-Aktivität nach Display-Schlaf aussetzen

🛠️ Schritt-für-Schritt-Lösung

Option 1: Client-Side-Fix (Sofortig - Für Benutzer)

Voraussetzung: Browser DevTools-Zugriff (F12)

  1. Öffnen Sie die Browser DevTools (F12)
  2. Navigieren Sie zum Tab Konsole
  3. Führen Sie das folgende Snippet vor der Inaktivitätsperiode aus:
// Prevent automatic reconnection from dropping auth
(function() {
  const originalConnect = window.OpenClawConnection?.connect;
  
  if (originalConnect) {
    window.OpenClawConnection.connect = function() {
      const token = localStorage.getItem('openclaw_auth_token');
      const result = originalConnect.call(this);
      
      // Inject auth after reconnection
      this.ws?.addEventListener('open', () => {
        this.ws.send(JSON.stringify({
          type: 'AUTH',
          token: token
        }));
      });
      
      return result;
    };
  }
  
  console.log('[OpenClaw] Auth preservation patch applied');
})();

Option 2: Serverkonfiguration (Für Administratoren)

Schritt 1: Gateway-Konfigurationsdatei finden:

# Linux/macOS
~/.openclaw/gateway.yaml

# Docker
docker exec openclaw-gateway cat /app/config/gateway.yaml

Schritt 2: Sitzungs-Timeout-Einstellungen ändern:

# Vorher (gateway.yaml)
server:
  session_timeout: 600  # 10 minutes

# Nachher (gateway.yaml)
server:
  session_timeout: 28800  # 8 hours
  websocket:
    ping_interval: 30    # Ping alle 30 Sekunden senden
    ping_timeout: 10     # Trennen, wenn kein Pong innerhalb von 10 Sekunden
  auth:
    token_refresh_interval: 300  # Token automatisch alle 5 Minuten erneuern

Schritt 3: Gateway-Dienst neu starten:

# Systemd
sudo systemctl restart openclaw-gateway

# Docker
docker restart openclaw-gateway

# Direktes Binary
./openclaw gateway restart

Option 3: Web-UI-Code-Fix (Für Entwickler)

Datei: web-ui/src/services/WebSocketManager.ts

// Vorher (defekte Wiederverbindungslogik)
class WebSocketManager {
  private handleReconnect() {
    this.socket = new WebSocket(this.url);
    // Fehlt: Authentifizierung bei neuer Verbindung
  }
}

// Nachher (korrigierte Implementierung)
class WebSocketManager {
  private handleReconnect() {
    this.socket = new WebSocket(this.url);
    
    this.socket.addEventListener('open', () => {
      this.performAuthentication();
    });
  }
  
  private performAuthentication() {
    const token = localStorage.getItem('openclaw_auth_token');
    if (token) {
      this.send({
        type: 'AUTH_HANDSHAKE',
        payload: {
          token: token,
          clientVersion: window.OPENCLAW_VERSION,
          reconnect: true
        }
      });
    }
  }
}

Zusätzlicher Fix für Session Store:

Datei: gateway/src/session/SessionStore.ts

// Vorher: Sitzungen laufen nur aufgrund von Timeout ab
async createSession(token: string): Promise {
  return this.sessions.create({
    token,
    expiresAt: Date.now() + SESSION_TIMEOUT
  });
}

// Nachher: Sitzungen können über Keepalive verlängert werden
async createSession(token: string): Promise {
  return this.sessions.create({
    token,
    expiresAt: Date.now() + SESSION_TIMEOUT,
    extendable: true
  });
}

async extendSession(sessionId: string): Promise {
  const session = await this.sessions.get(sessionId);
  if (session?.extendable) {
    session.expiresAt = Date.now() + SESSION_TIMEOUT;
    await this.sessions.update(sessionId, session);
  }
}

Option 4: Versionssynchronisierung (Für Versionskonflikt-Bug)

# Alle OpenClaw-Dienste stoppen
openclaw stop --all

# Zwischengespeicherte Assets löschen
rm -rf ~/.openclaw/cache/web-ui/
rm -rf ~/.openclaw/cache/assets/

# Neuinstallation zur Versionssynchronisierung
openclaw update --force

# Dienste neu starten
openclaw start --all

🧪 Verifizierung

Testfall 1: Basis-Wiederverbindung

# Terminal 1: Gateway-Logs überwachen
openclaw logs --follow gateway

# Browser: DevTools-Konsole öffnen und nach "OpenClaw" filtern
# Ausführen: Tab genau 12 Minuten lang inaktiv lassen

# Erwartet: Keine 401-Fehler nach Wiederverbindung
# Konsole sollte zeigen:
#   [OpenClaw] Connection lost
#   [OpenClaw] Reconnecting...
#   [OpenClaw] Auth sent
#   [OpenClaw] Reconnected successfully

Testfall 2: WebSocket-Ping/Pong-Verifizierung

# Im Browser-Consale Ping/Pong-Verkehr verifizieren
setInterval(() => {
  console.table({
    wsState: WebSocket.CONNECTING, // 0
    wsOpen: WebSocket.OPEN,        // 1
    wsClosing: WebSocket.CLOSING,  // 2
    wsClosed: WebSocket.CLOSED     // 3
  });
}, 60000); // Alle Minute prüfen

# Erwartet: Status bleibt OPEN während der Hintergrundung

Testfall 3: Sitzungspersistenzprüfung

# Sitzungs-TTL über Gateway-API prüfen
curl -s http://127.0.0.1:18789/api/v1/session/status \
  -H "Authorization: Bearer $(cat ~/.openclaw/auth_token)" \
  | jq .session

# Erwartete Ausgabe:
# {
#   "sessionId": "sess_abc123",
#   "expiresAt": "2026-01-16T00:00:00Z",
#   "ttl": 28800,
#   "extendable": true
# }

Testfall 4: Lasttest (Automatisiert)

# Testsuite für Sitzungs-Timeout ausführen
npm test -- --grep "session-timeout"

# Erwartete Ergebnisse:
#   ✓ reconnect-with-auth: Keine 401 nach 15 Min. Inaktivität
#   ✓ token-refresh: Token wurde vor Ablauf automatisch erneuert
#   ✓ multiple-reconnects: Auth über 5 Wiederverbindungszyklen hinweg bewahrt

Verifizierungs-Checkliste

TestBefehlErwartetes Ergebnis
Gateway erreichbarcurl http://127.0.0.1:18789/health{“status”: “ok”}
WebSocket-Upgradewebsocat ws://127.0.0.1:18789/wsVerbindung hergestellt
Auth-Token gültiglocalStorage.openclaw_auth_token prüfenNicht-leerer JWT-String
Versionssyncopenclaw versionEntspricht Browser-UI-Version

⚠️ Häufige Fehler

Fallstrick 1: Browser-Datenschutz/Inkognito-Modus

Problem: localStorage wird bei Verwendung des Inkognito-/Privaten Browsens im strengen Modus gelöscht.

Symptom: Authentifizierung schlägt selbst nach Seitenaktualisierung fehl.

Workaround:

# Prüfen, ob localStorage zugänglich ist
console.log(localStorage.getItem('openclaw_auth_token'));
// Wenn null im Inkognito: Persistente Speicheroption in Einstellungen verwenden

Fallstrick 2: Docker-Netzwerksegmentierung

Problem: WebSocket-Verbindungen vom Browser können sich anders durch Docks internales NetzwerkRouting als HTTP.

Symptom: HTTP 401 trotz korrektem Token; WebSocket-Upgrade schlägt fehl.

Diagnose:

# Docker-Portzuordnungen prüfen
docker port openclaw-gateway

# Verifizieren, dass WebSocket-Endpunkt exponiert ist
curl -I http://localhost:18789/ws
# Sollte zurückgeben: 101 Switching Protocols

Fix:

# docker-compose.yaml Ergänzung
services:
  gateway:
    ports:
      - "18789:18789"    # HTTP/REST
      - "18790:18790"    # WebSocket (falls separrat)

Fallstrick 3: macOS Akku/Energiesparmodus

Problem: macOS kann die JavaScript-Ausführung in Hintergrund-Tabs drosseln und verhindert so Ping/Pong-Keepalive.

Symptom: Sitzungen laufen ab, selbst mit kurzem konfiguriertem Timeout.

Workaround:

# App Nap für Browser deaktivieren
# Safari: Entwickler → Experimentelle Funktionen → Hintergrund-Timer-Drosselung deaktivieren
# Chrome: --disable-background-timer-throttling Flag hinzufügen
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-background-timer-throttling

Fallstrick 4: Reverse-Proxy-Timeout

Problem: Nginx/Apache kann WebSocket-Verbindungen wegen proxy_read_timeout schließen.

Symptom: 401 erscheint genau beim Proxy-Timeout, nicht beim Gateway-Timeout.

Fix:

# nginx.conf
location /ws {
    proxy_pass http://127.0.0.1:18789;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;  # 24 Stunden
    proxy_send_timeout 86400;
}

Fallstrick 5: Authentifizierung mit mehreren Tabs

Problem: Das Öffnen mehrerer Tabs erstellt mehrere Sitzungen; das Schließen eines Tabs kann andere invalidieren, wenn der Einzelsitzungsmodus verwendet wird.

Symptom: 401 erscheint nach dem Öffnen eines zweiten Tabs und dessen Schließen.

Workaround: Multi-Session-Modus in der Gateway-Konfiguration aktivieren:

# gateway.yaml
auth:
  allow_concurrent_sessions: true
  session_mode: per-tab  # Anstatt per-user

Fallstrick 6: Token-Ablauf vs. Sitzungsablauf

Problem: JWT kann unabhängig von der WebSocket-Sitzung ablaufen.

Symptom: 401 selbst unmittelbar nach der Authentifizierung.

Diagnose:

# JWT dekodieren, um Ablaufzeit zu prüfen
atob(localStorage.openclaw_auth_token.split('.')[1])
# "exp" Claim suchen - Unix-Zeitstempel

# Mit aktueller Zeit vergleichen
date +%s

🔗 Zugehörige Fehler

Zugehörige HTTP-Fehler

FehlercodeProblemVerbindung
401 UnauthorizedUngültiges/abgelaufenes AuthentifizierungstokenDirekter Nachfolger dieses Problems
403 ForbiddenGültiges Token aber unzureichende BerechtigungenVerwandter Authentifizierungsablauf
407 Proxy Authentication RequiredProxy-Anmeldedaten erforderlichAndere Schicht

Zugehörige WebSocket-Schließcodes

SchließcodeNameBeschreibung
1000Normal ClosureBeabsichtigtes Trennen
1001Going AwayServer fährt herunter
1006Abnormal ClosureNetzwerkfehler oder Timeout (unser Fall)
1011Unexpected ErrorServerseitiger Fehler
4001Authentication FailedBenutzerdefinierter Gateway-Code

Historische Probleme in OpenClaw

  1. Issue #2847: "WebSocket trennt zufällig während langer Konversationen" - Ähnlicher Timeout-Mechanismus
  2. Issue #2901: "Auth-Token wird nicht über Browser-Neustart hinweg beibehalten" - localStorage-Grenzfall
  3. Issue #3102: "Versionskonflikt zwischen CLI und Web-UI" - Verwandt mit der in diesem Bericht festgestellten Versionsdiskrepanz
  4. Issue #3156: "Dashboard erfordert alle 5 Minuten erneute Anmeldung" - Variante mit kürzerem Timeout
  5. Issue #3224: "WebSocket-Ping funktioniert nicht in Hintergrund-Tabs" - macOS-spezifisch

Zugehörige Dokumentation

Bekannte betroffene Versionen

Vulnerable versions: 2026.2.10 - 2026.2.23
Fixed in version: 2026.2.24 (pending release)
Partial fix: 2026.2.18 (ping implementation added, but not active by default)

Belege & Quellen

Diese Troubleshooting-Anleitung wurde automatisch von der FixClaw Intelligence Pipeline aus Community-Diskussionen synthetisiert.