# Calls scheitern still, obwohl Login und Messaging laufen

**Symptom:** Ein Nutzer kann sich anmelden und Nachrichten schreiben, aber **kein
Anruf kommt zustande**. Beim Klick auf „Anruf" passiert serverseitig *nichts* —
kein `openid/request_token`, kein `call.member`-Event, keine Fehlermeldung. Das
Element-Call-Widget-iframe bleibt leer bzw. lädt ewig.

Zuerst live gesehen bei `@apo` am 2026-08-11 (Vor-Authentik-Konto, durch mehrere
Identitäts-Resets gegangen).

## Grundursache

Dem Konto fehlt seine Zeile in Synapses **`profiles`-Tabelle**. Jeder registrierte
Nutzer hat eine; Deaktivieren löscht sie, Reaktivieren legt sie **nicht** neu an.
Ein Konto ohne diese Zeile läuft für Messaging weiter, aber:

1. `PUT /_matrix/client/v3/profile/<user>/displayname` crasht mit
   **`TypeError: 'NoneType' object is not subscriptable`** in
   `_check_profile_size` (`synapse/storage/databases/main/profile.py`). Die
   Größenprüfung macht `txn.fetchone()` und indiziert das Ergebnis — bei fehlender
   Zeile ist das `None`. Der Client meldet „Anzeigename konnte nicht gesetzt
   werden". *(Synapse-Bug: der Code setzt die Zeile als immer vorhanden voraus.)*
2. Dadurch bleibt der Displayname leer — global **und** in der Raum-Mitgliedschaft.
3. Element Web baut die Element-Call-Widget-URL u. a. aus dem Displaynamen. Fehlt
   er überall, initialisiert das **Widget-iframe nie** (meldet nie `ContentLoaded`,
   in der Browser-Konsole als „Messaging present but not yet started" sichtbar).
4. Ohne aktives Widget wird nie ein OpenID-Token angefragt, also nie die SFU
   erreicht — der ganze Call-Pfad bleibt stumm.

## Diagnose (read-only, in dieser Reihenfolge)

```bash
# 1) Das Alarmsignal: ein sonst aktiver Nutzer OHNE OpenID-Token.
#    open_id_tokens werden nicht geprunt — wer je telefoniert hat, hat Einträge.
kubectl exec -n matrix matrix-stack-postgres-0 -c postgres -- \
  psql -U postgres -d synapse -At -c \
  "SELECT count(*) FROM open_id_tokens WHERE user_id='@NAME:axion1337.chat'"
#    -> 0 bei einem aktiven Konto ist verdächtig.

# 2) Die Bestätigung: fehlt die profiles-Zeile?
kubectl exec -n matrix matrix-stack-postgres-0 -c postgres -- \
  psql -U postgres -d synapse -At -c \
  "SELECT count(*) FROM profiles WHERE full_user_id='@NAME:axion1337.chat'"
#    -> 0 = das ist die Ursache.

# 3) Confounder ausschließen: ist der Testraum verschlüsselt?
#    Wenn NICHT, ist Krypto/Cross-Signing als Ursache raus.
kubectl exec -n matrix matrix-stack-postgres-0 -c postgres -- \
  psql -U postgres -d synapse -At -c \
  "SELECT ev.type FROM current_state_events cse JOIN events ev ON ev.event_id=cse.event_id
   WHERE cse.room_id='!RAUM:axion1337.chat' AND ev.type='m.room.encryption'"
```

Optional der harte Beleg im Log (der Displayname-500 erscheint beim Setzversuch):
```bash
kubectl logs -n matrix matrix-stack-synapse-main-0 --tail=3000 | grep -A15 ProfileFieldRestServlet
```

## Fix

Die fehlende Registrierungs-Default-Zeile nachtragen. **Nur `user_id` (Localpart)
und `full_user_id` sind nötig, der Rest bleibt NULL** — an gesunden Konten
(`clark`, `calltest01`) gegengeprüft. Vorher immer die (fehlende) Zeile anzeigen,
nichts überschreiben:

```bash
kubectl exec -n matrix matrix-stack-postgres-0 -c postgres -- \
  psql -U postgres -d synapse -c \
  "INSERT INTO profiles (user_id, full_user_id)
   VALUES ('NAME','@NAME:axion1337.chat') ON CONFLICT (user_id) DO NOTHING
   RETURNING *;"
```

Danach: der Nutzer setzt im Client seinen Anzeigenamen (funktioniert jetzt),
`open_id_tokens` füllt sich beim nächsten Call-Versuch, der Anruf läuft.

## Verifikation

```bash
# displayname gesetzt, open_id_tokens > 0, call.member vorhanden
kubectl exec -n matrix matrix-stack-postgres-0 -c postgres -- psql -U postgres -d synapse -At -c \
 "SELECT (SELECT displayname FROM profiles WHERE full_user_id='@NAME:axion1337.chat'),
         (SELECT count(*) FROM open_id_tokens WHERE user_id='@NAME:axion1337.chat')"
```

## Wen es betrifft

Nur Konten **ohne** `profiles`-Zeile — praktisch nur alte, mehrfach
zurückgesetzte/deaktivierte-und-reaktivierte Konten. Frisch über den
Einladungs-Flow provisionierte Konten bekommen den Displaynamen aus Authentiks
`{{ user.name }}`-Claim und haben die Zeile immer. Am 2026-08-11 war `@apo` der
einzige betroffene *lebende* Nutzer (`frank` hatte seine Zeile;
`crank`/`shank`/`stank` sind deaktiviert).
