---
url: 'https://www.corbado.com/de/blog/webauthn-fehler'
title: 'Der ultimative Guide für WebAuthn-Fehler in Produktion (2026)'
description: 'Erfahren Sie, was häufige WebAuthn-Fehler wie NotAllowedError in Produktion bedeuten und wie Sie sie nach Operationstyp, Timing und Plattform-Kontext klassifizieren.'
lang: 'de'
author: 'Vincent Delitz'
date: '2026-07-03T07:09:49.619Z'
lastModified: '2026-07-03T07:10:43.637Z'
keywords: 'webauthn fehler, NotAllowedError, AbortError, SecurityError, WebAuthn fehlersuche, passkey fehlerklassifizierung, conditional create fehler, ASAuthorizationError, ASAuthorizationError codes, androidx.credentials, Credential Manager passkey fehler, iOS'
category: 'WebAuthn Know-How'
---

# Der ultimative Guide für WebAuthn-Fehler in Produktion (2026)

## 1. Einleitung

In Produktion sind WebAuthn-Fehler oft verwirrend, da Browser nur eine kleine Menge an `DOMException`-Namen (wie `NotAllowedError`) offenlegen, die verschiedene zugrundeliegende Ursachen haben können. Zudem sind die allermeisten "Fehler" – in optimierten, großen Implementierungen oft über 95 % – tatsächlich **erwartetes Verhalten** (der Nutzer hat den Passkey-Prompt des Betriebssystems abgebrochen).

> Wichtig: Aus Datenschutzgründen unterscheiden Browser nicht, ob der Nutzer aktiv abgebrochen hat oder ob kein Passkey vorhanden war. In einigen Situationen und mit ausreichendem Kontext können diese beiden Fälle jedoch sowohl im Web als auch auf nativen Plattformen anhand von Signalen wie dem Timing unterschieden werden.

Wenn Sie die kanonischen Definitionen für diese Namen suchen, beginnen Sie mit [MDN `DOMException`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException). Für WebAuthn-spezifische Bedingungen, die zu diesen Ausnahmen führen (und was Browser erzwingen müssen), siehe die [W3C Web Authentication Spec](https://www.w3.org/TR/webauthn-3/).

Wenn Sie alle Fehler als „Bugs“ behandeln, tun Sie das Falsche:

- Sie verfälschen Ihre Fehlermetriken durch normale Abbrüche.
- Sie übersehen echte Regressionen, die sich in der Masse an `NotAllowedError` verbergen.
- Sie liefern eine UI aus, die Nutzer verwirrt, anstatt ihnen bei der Wiederherstellung zu helfen.

In diesem Artikel beantworten wir:

- Was bedeuten die häufigsten WebAuthn-Fehlernamen normalerweise im echten Traffic?
- Wie unterteilen Sie `NotAllowedError` in handlungsrelevante Kategorien (Abbruch vs. Timeout vs. Verfügbarkeit)?
- Warum bedeutet derselbe Fehler je nach Operation (Conditional UI Login vs. modaler Login vs. Passkey-Erstellung vs. Conditional Create) etwas anderes?
- Welchen Mindestkontext sollten Sie erfassen, damit aus einem "Es ist fehlgeschlagen" ein reproduzierbares Problem wird?

## Key Facts

- `NotAllowedError` ist ein **Oberflächensignal**, keine Grundursache. Es kann Abbruch, Timeout, "keine lokale Credential vorhanden" oder fehlende Nutzeraktivierung bedeuten, je nach Kontext.
- **Der Operationstyp ändert die Bedeutung.** Derselbe `NotAllowedError` bedeutet etwas anderes bei einem Conditional UI Login, modalen Login, manueller Passkey-Erstellung, Conditional Create und automatisch ausgelösten Appends.
- **Timing seit dem Start der Operation** ist das am meisten unterschätzte Signal: sofortig (`<1s`), Nutzerabbruch (1 bis 15 s) und Timeout (30+ s) sind grundlegend unterschiedliche Kategorien.
- `AbortError` ist meist ein Lebenszyklus-/Nebenläufigkeitsproblem (Navigation, Re-Render, mehrere laufende Anfragen).
- `SecurityError` liegt fast immer an der Konfiguration/am Kontext und ist in ausgereiften Produktionsumgebungen selten.
- "Browser-Fehlernamen" und "Server-Verifizierungsablehnungen" sind verschiedene Ebenen. Verfolgen Sie Serverablehnungen als explizite Codes, nicht als generische Client-Fehler.
- **Rohe Fehlernamen sind allein nicht handlungsrelevant.** Erfassen Sie immer den Operationstyp, das Timing und den Plattform-Kontext zusammen mit `error.name`, damit Sie Fehler in Kategorien einteilen können, die Sie tatsächlich beheben können.
- **"Umgebung" ist mehr als nur Browser + OS.** Um Fehler wirklich zu verstehen, müssen Sie die gesamte Kombination tracken: OS-Version, Client (Browser/App-Version), Authenticator-Einstellungen (z. B. iCloud/GPM-Status) und das spezifische Hardware-Modell.
- **Login-Fehler sind P1, Erstellungs-Fehler sind P2.** Während Erstellungs-Fehler (P2) oft ein höheres Volumen aufgrund von Nutzerabbrüchen haben, blockieren Login-Fehler (P1) den Zugang und erfordern sofortige Warnungen.

## 2. Ein Produktions-Cheat-Sheet

Wenn Sie nur eine schnelle Übersicht zur Fehlersuche benötigen, beginnen Sie mit dieser Tabelle. Sie konzentriert sich darauf, was Teams in Dashboards und Support-Tickets tatsächlich sehen.

| **`error.name`**    | **Was es in Produktion meistens bedeutet**                                                                                                        | **Was zur Bestätigung zu prüfen ist**                                                                          | **Erste Maßnahme (UX + Engineering)**                                                                           |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `NotAllowedError`   | Nutzer hat Dialog geschlossen, Timeout oder Verfügbarkeitskonflikt, in einer Kategorie zusammengefasst. Die größte Fehlerkategorie in Produktion. | Time-to-Error, ob QR/Hybrid-UI erschien, ob Zeremonie durch echte Nutzeraktion gestartet wurde                 | Als erwartet behandeln: UI wiederherstellen + Fallback anzeigen                                                 |
| `AbortError`        | Ihre App (oder der Browser) hat die Zeremonie abgebrochen                                                                                         | Navigation/Re-Render während Zeremonie; gleichzeitige WebAuthn-Aufrufe; `AbortController.abort()`              | Nur eine laufende Anfrage zulassen; Routenänderungen verhindern; Abbruch als normalen Kontrollfluss behandeln   |
| `SecurityError`     | Kontext/Richtlinie nicht erlaubt                                                                                                                  | Origin + RP-ID-Strategie; iFrame/Einbettung; HTTPS; Feature Policy                                             | RP-ID/Origin-Konfiguration korrigieren; Einbettungsrichtlinien validieren; sicheren Kontext sicherstellen       |
| `InvalidStateError` | Statusinkonsistenz (oft doppelte Registrierung)                                                                                                   | Registrierung vs. Login; `excludeCredentials`; existierende Credential auf dem Authenticator                   | Als „bereits registriert“ behandeln; UX-Pfad anpassen; Optionsgenerierung korrigieren                           |
| `ConstraintError`   | Anforderungen können nicht erfüllt werden                                                                                                         | `authenticatorAttachment`, `userVerification`, Resident-Key-Anforderungen                                      | Anforderungen lockern oder alternativen Pfad/Fallback anbieten. Beispiel: Bildschirmsperre fehlt unter Android  |
| `DataError`         | Eingaben sind fehlerhaft/inkonsistent                                                                                                             | Base64url-Kodierung; Formate von ID/Challenge/User Handle                                                      | Kodierung/Serialisierung korrigieren; Validierung bei Optionsgenerierung hinzufügen                             |
| `NotSupportedError` | Plattform/Browser unterstützt nicht, was Sie angefordert haben                                                                                    | OS/Browser-Version; Annahmen bei Feature-Erkennung                                                             | Sofort auf Fallback ausweichen; Segment erfassen; Passkey-CTAs in nicht unterstützten Umgebungen vermeiden      |
| `UnknownError`      | Plattform/Authenticator ist auf generische Weise fehlgeschlagen                                                                                   | Spitzen nach OS-Updates; Geräte-Build; Probleme mit Credential-Manager-Anbietern                               | Retry-freundliche UX; Build-Nummern erfassen; Segmentspezifische Spitzen untersuchen                            |

Eines wird leicht übersehen: Derselbe `error.name` kann je nach **Operationstyp** völlig unterschiedliche Dinge bedeuten. Behalten Sie den Kontext der Operation im Hinterkopf, wenn Sie die folgenden Abschnitte lesen. In der Praxis übertreffen Erstellungsfehler (Registrierung) Login-Fehler meist bei Weitem – die obige Tabelle gilt für beides, aber bei der Erstellung liegt das größte Volumen.

Als Nächstes gehen wir detaillierter auf den `NotAllowedError` ein, da dies der Fehler ist, den Sie am häufigsten sehen werden und der von Teams am häufigsten falsch interpretiert wird.

## 3. NotAllowedError: Die Operation ist abgelaufen oder war nicht erlaubt

Ein `NotAllowedError` sieht oft so aus, als ob "Passkeys fehlgeschlagen" wären, aber meist teilt Ihnen die Plattform lediglich mit, dass der Nutzer die OS-UI nicht abgeschlossen hat. Der Schlüssel ist, dies in Kategorien zu unterteilen, auf die Sie reagieren können.

**Was Sie in der Browser-Konsole sehen werden:**

| **Quelle**     | **Fehlermeldung**                                                                                                                                                    |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Chrome, Edge   | `NotAllowedError: The operation either timed out or was not allowed. See: https://www.w3.org/TR/webauthn-2/#sctn-privacy-considerations-client.`                     |
| Safari, WebKit | `NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.`                 |
| Safari, WebKit | `NotAllowedError: This request has been cancelled by the user.`                                                                                                      |
| Chrome, Edge   | `NotAllowedError: The operation is not allowed at this time because the page does not have focus.`                                                                   |
| Safari, WebKit | `NotAllowedError: The document is not focused.`                                                                                                                      |
| Firefox        | `NotAllowedError: Operation failed.`                                                                                                                                 |

All diese Meldungen treten als `error.name === "NotAllowedError"` auf. Die `error.message` variiert je nach Browser-Engine und zugrundeliegender Ursache, aber das Ergebnis ist dasselbe: Die Zeremonie wurde nicht abgeschlossen.

Dies gilt sowohl für den **Login als auch für die Passkey-Erstellung**. Beim Login (Conditional UI, modal mit oder ohne allowList) bedeutet ein `NotAllowedError` typischerweise, dass der Nutzer die Zeremonie nicht beendet hat. Bei der Passkey-Erstellung tritt derselbe Fehler aus anderen Gründen auf: Der Nutzer hat den Erstellungsdialog geschlossen, Conditional Create hat nicht funktioniert oder die Seite hat während eines automatisch ausgelösten Appends den Fokus verloren. Der Operationstyp ändert, was der Fehler bedeutet und was Sie tun sollten.

**Timing ist oft ein unterschätztes Signal.** Ein Fehler in weniger als einer Sekunde nach einem Klick ist meist eine sofortige Ablehnung (Umgebung kann es nicht, Dokument nicht fokussiert, fehlende Fähigkeit). Ein Fehler nach einigen Sekunden ist ein Nutzerabbruch (sie haben den Dialog gesehen und sich dagegen entschieden). Ein Fehler nach über 30 Sekunden ist ein Timeout. Auf nativen Plattformen ist das Timing besonders wichtig: Authenticator-Roundtrips, biometrische Prompts und Credential-Manager-Übergaben haben alle charakteristische Dauern, die Ihnen helfen, ein "Hat nicht funktioniert" von einem "Nutzer ist weggegangen" zu unterscheiden. Sie können dennoch nicht ohne Weiteres unterscheiden, ob ein Passkey existierte.

### 3.1 Disambiguierung durch Kontext

Sie benötigen kein perfektes Signal. Sie brauchen genug Kontext, um zu vermeiden, dass jeder `NotAllowedError` gleich behandelt wird. iOS/Safari wird unten speziell behandelt, da es besondere Einschränkungen hat (Anforderungen an die Nutzeraktivierung in früheren Versionen), aber was das reine Fehlervolumen betrifft, generieren Windows und Chromium-Browser oft mehr `NotAllowedError` als jede andere Plattform. Diese Signale bringen Sie oft zu 80 % ans Ziel:

| **Signal**                                                          | **Wahrscheinliche Bedeutung**                                                                                                                                                                                                                                                             | **Was als Nächstes zu tun ist**                                                                                                                                                                   |
| ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sofortiger Fehler (`<1s`)                                           | Ablehnung durch Umgebung: Keine Funktion, Dokument nicht fokussiert, Conditional-Create-Oberfläche nicht verfügbar                                                                                                                                                                        | Feature-Erkennung prüfen; sicherstellen, dass Dokument fokussiert ist; verifizieren, ob Operation auf dieser Plattform unterstützt wird                                                           |
| Schneller Abbruch (1-3s)                                            | Überraschender Prompt / fehlender Kontext                                                                                                                                                                                                                                                 | Prompt-Timing ändern; Cooldown nach Abbruch hinzufügen                                                                                                                                            |
| Abbruch durch Nutzer (3-15s)                                        | Nutzer hat den Dialog gesehen und sich dagegen entschieden                                                                                                                                                                                                                                | Erwartete UX; UI wiederherstellen + Fallback anzeigen                                                                                                                                             |
| Timeout (30s+)                                                      | Zeremonie ist ohne Nutzeraktion abgelaufen                                                                                                                                                                                                                                                | Als "nicht abgeschlossen" einkategorisieren; überlegen, ob der Prompt wahrgenommen wurde                                                                                                          |
| QR/Hybrid-UI erscheint vor Fehler                                   | Keine lokale Credential auf diesem Gerät verfügbar. Hinweis: Die zuverlässige Erkennung von Entscheidungen im QR-Code, bevor sie eintreffen, erfordert einen [Passkey-Intelligence](https://docs.corbado.com/corbado-connect/features/passkey-intelligence)-Layer, der weiß, ob eine nutzbare Credential auf dem aktuellen Gerät existiert.                         | Passkey-Angebote absichern; "Telefon verwenden" explizit machen; überraschende QR-Codes reduzieren                                                                                                |
| Konzentriert auf iOS/Safari und ausgelöst ohne Klick/Tippen         | Fehlende Nutzeraktivierung                                                                                                                                                                                                                                                                | Zeremonie durch eine echte Nutzeraktion starten                                                                                                                                                   |
| Bei Conditional Create oder automatisch ausgelöstem Append          | Autofill nicht verfügbar, Credential existiert bereits, oder Seite hat Fokus verloren. Conditional-Create-Fehler können beim Start des Features plötzlich und in hohem Volumen auftreten, was dies über Nacht zu einer der größten Fehlerquellen macht.                                   | Siehe Conditional Create; Dokumenten-Sichtbarkeitsstatus prüfen; `getClientCapabilities()` verwenden, um `conditionalCreate`-Unterstützung vor dem Aufruf zu verifizieren                         |

Das ist auch der Grund, warum ein `NotAllowedError` selten für den Nutzer sichtbar sein sollte. Es ist keine Nachricht, auf die der Nutzer reagieren kann.

Die Kontext-Klassifizierung ist auch der Bereich, in dem sich die Erfolgsraten am deutlichsten unterscheiden. Die [Passkey-Erfolgsratenanalyse des Corbado Passkey-Benchmarks 2026](https://www.corbado.com/passkey-benchmark-2026/passkey-authentication-success-rate) misst im ersten Quartal 2026 eine Abschlussrate von 55–95 % für Identifier-First-Flows auf unbekannten Geräten, verglichen mit 95–99 % für wiederkehrende Nutzer auf bekannten Geräten über große B2C-Implementierungen hinweg.
Web-Identifier-First auf iOS erreicht 85–95 % Abschluss (% CDA 0–5 %), Android Web 70–85 % (% CDA 5–10 %) und macOS Web 70–85 % (% CDA 10–15 %), während Windows Web bei 45–60 % Identifier-First-Abschluss liegt, mit % CDA bei 55–65 % unter Windows 11 und 40–55 % unter Windows 10. Das Lesen des `NotAllowedError`-Volumens ohne Trennung von Kontexten auf bekannten und unbekannten Geräten vermischt zwei grundlegend unterschiedliche Erfolgsregime.

Eine Nuance, die in Produktion wichtig ist: Einige User-Agents zeigen Timeouts als `TimeoutError` an, aber viele Teams sehen in Dashboards, dass Timeouts unter `NotAllowedError` zusammengefasst werden. Behandeln Sie Timeouts in jedem Fall als „Zeremonie wurde nicht abgeschlossen“ und klassifizieren Sie anhand von Timing plus Kontext.

### 3.2 UX-Handling: Machen Sie Abbrüche zu einem normalen Exit

Wenn der OS-Dialog geschlossen wird oder ein Timeout auftritt, sollte sich Ihre UI sofort erholen und elegant reagieren. Ein praktisches Set an Regeln:

- UI für das Login wiederherstellen (keine unendlich ladenden Spinner)
- Identifier-Status beibehalten (keine erneute Eingabe erzwingen)
- Sichtbaren Fallback auf demselben Bildschirm anzeigen
- Beängstigende Warnhinweise für erwartete Ergebnisse vermeiden

Darüber hinaus:

- Behandeln Sie den ersten Abbruch als normal und bieten Sie einen erneuten Versuch mit einer ruhigen Erklärung an. Erst nach einem zweiten Abbruch sollten Sie Fallback-Optionen vorschlagen.
- Erlauben Sie bis zu drei Erstellungs-Prompts vor einem Cooldown, damit überraschte Nutzer eine zweite Chance erhalten.
- Trennen Sie Fehlerzählungen nach Erstellung und Logins, damit Sie Äpfel mit Äpfeln vergleichen.
- Segmentieren Sie Fehlerraten nach OS, Browser und Gerät, damit Sie erkennen können, wo tatsächliche Reibungspunkte liegen.

Wenn Ihre „Abbrüche“ wirklich hoch sind, ist der nächste Schritt, die Grundursachen dahinter zu beheben: Prompt-Timing, QR-Überraschungen und geringe Verfügbarkeit.

### 3.3 Engineering-Fixes, die NotAllowedError reduzieren

Beginnen Sie mit Änderungen, die Metriken schnell verbessern:

- Prompt-Timing und Nutzeraktivierung korrigieren (insbesondere bei iOS/Safari).
- QR/Hybrid-Überraschungen reduzieren.
- Passkey-Angebote so platzieren, dass sie nur angezeigt werden, wenn sie wahrscheinlich erfolgreich sind.
- Muster verwenden, die keine Prompts auslösen, wenn keine lokale Credential vorhanden ist.
- **Umgang mit Netzwerkinstabilitäten:** Netzwerkfehler während der Überprüfung äußern sich oft als generische clientseitige Fehler. Implementieren Sie eine Offline-Warteschlange für Ihre Telemetrie-Logs, damit keine Fehlerdaten verloren gehen, wenn die Verbindung des Nutzers während der Zeremonie abbricht.
- **Zeremonien durch Erkennungs-APIs absichern**, damit Fehler der Umgebung Ihre `NotAllowedError`-Kategorie nicht aufblähen. Beginnen Sie mit `isUVPAA()` als Basisüberprüfung und nutzen Sie dann `getClientCapabilities()` für feinere Prüfungen (Conditional Create, Conditional Get, Hybrid Transport, Platform Authenticator). Beachten Sie, dass Erkennungs-APIs durch OS-Updates kaputtgehen können: iOS 26.2 lieferte einen WebKit-Bug aus, bei dem `isUVPAA()` in allen WKWebView-basierten Browsern `false` zurückgibt, obwohl Passkeys problemlos funktionieren, was zu plötzlichen Spitzen bei `NotAllowedError` für 10 bis 25 % der iOS-Nutzer führte.

### 3.4 Hinweis zu sich ändernden Fehlernamen

Fehlernamen sind im Wandel. Es gibt aktuelle Vorschläge, granulare WebAuthn-Fehler einzuführen (z. B. um „keine Credential verfügbar“ von „Nutzer hat abgebrochen“ zu trennen). Stand Februar 2026 ist dies noch in keinem Browser implementiert, daher lohnt es sich nach wie vor, eigene Ursachen-Kategorien basierend auf Kontext und Timing aufzubauen. Wenn Sie diese Arbeit verfolgen möchten, siehe [WebAuthn-Issue #2062](https://github.com/w3c/webauthn/issues/2062) und den ["New Error Codes" Explainer](https://github.com/w3c/webauthn/wiki/Explainer%3A-New-Error-Codes-%282024-Edition%29).

Die übrigen Fehlernamen treten seltener auf, sollten aber dennoch verstanden werden, wenn sie auftauchen.

## 4. AbortError: Die Operation wurde abgebrochen

Ein `AbortError` tritt im Vergleich zum `NotAllowedError` selten in großen Mengen auf, aber wenn er auftaucht, ist er stark diagnostisch: Er bedeutet normalerweise, dass die Zeremonie nicht abgeschlossen wurde, weil Ihre App die Anfrage ungültig gemacht hat – es fand eine Navigation statt, der Status änderte sich oder eine zweite Anfrage wurde gestartet.

**Was Sie in der Browser-Konsole sehen werden:**

| **Quelle**     | **Fehlermeldung**                                         |
| -------------- | --------------------------------------------------------- |
| Chrome, Edge   | `AbortError: The operation was aborted.`                  |
| Chrome, Edge   | `AbortError: Aborted by AbortSignal.`                     |
| Firefox        | `AbortError: signal is aborted without reason`            |
| Firefox        | `AbortError: Operation timed out.`                        |
| Safari, WebKit | `AbortError: The user aborted a request.`                 |
| Chrome         | `AbortError: CredentialContainer request is not allowed.` |

Häufige Ursachen in Produktion sind:

- mehrere gleichzeitige WebAuthn-Aufrufe (zwei Prompts im Wettlauf)
- Routenänderung/Re-Render während einer laufenden Zeremonie
- Aufruf von `AbortController.abort()` während Wiederholungsversuchen oder beim Aufräumen des Status

Um das Problem zu beheben, konzentrieren Sie sich darauf, die Zeremonie zu einem „kritischen Bereich“ zu machen:

- Erlauben Sie nur eine laufende Anfrage zur gleichen Zeit
- Blockieren Sie Navigation während der Zeremonie (oder brechen Sie sauber ab und stellen Sie die UI wieder her)
- Behandeln Sie den Abbruch als normalen Kontrollfluss: Zeigen Sie einen Wiederholen-Button und eine Fallback-Methode an

Wenn sich `AbortError` in eingebetteten Ansichten oder Multi-Domain-Apps häuft, ist der nächste zu prüfende Bereich `SecurityError`.

## 5. SecurityError: WebAuthn wird auf Seiten mit TLS-Zertifikatsfehlern nicht unterstützt

Ein `SecurityError` ist die Mitteilung des Browsers: „Dieser Kontext darf nicht tun, was Sie verlangt haben.“ In der Praxis handelt es sich fast immer um ein Konfigurationsproblem, nicht um Nutzerverhalten. In ausgereiften Produktionsimplementierungen sind `SecurityError` selten, da diese Probleme typischerweise bei Integrationstests aufgefangen werden. Wenn sie in der Produktion auftreten, bedeutet dies normalerweise, dass eine neue Domain, ein Einbettungskontext oder ein Deployment-Ziel ohne ordnungsgemäße WebAuthn-Konfiguration hinzugefügt wurde.

Häufige Ursachen sind:

- RP-ID-/Origin-Unstimmigkeiten (Multi-Domain-Setups)
- Einschränkungen durch Cross-Origin-Einbettungen (iFrames)
- Unsicherer Kontext (nicht HTTPS) oder blockierte Berechtigungen/Richtlinien
- `.well-known/webauthn` oder `.well-known/assetlinks.json` ist falsch konfiguriert, fehlt oder ist vorübergehend nicht verfügbar. Netzwerkprobleme während des kritischen Zeitfensters, in dem der Browser diese Dateien abruft, führen zu Ausfällen. Ein häufiger blinder Fleck: Wenn Ihre Startseite wegen Wartungsarbeiten offline ist, sind auch die well-known Dateien offline, was Passkey-Zeremonien für alle auf sie angewiesenen Relying Parties beeinträchtigt.

**Was Sie in der Browser-Konsole sehen werden:**

| **Quelle**      | **Fehlermeldung**                                                                                                                |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Chrome, Edge    | `SecurityError: WebAuthn is not supported on sites with TLS certificate errors.`                                                 |
| Jeder Browser   | `SecurityError: The relying party ID is not a registrable domain suffix of, nor equal to the current origin's effective domain.` |
| Chrome (iFrame) | `SecurityError: The 'publickey-credentials-create' feature is not enabled in this document.`                                     |

In der Produktion ist ein `SecurityError` selten – diese werden fast immer in Integrationstests abgefangen. Wenn sie dennoch auftreten, ist ein TLS-Zertifikatsfehler die häufigste verbleibende Ursache.

Der schnellste Debugging-Prozess lautet:

- Loggen Sie die verwendeten Origin- und RP-ID-Eingaben
- Reproduzieren Sie das Problem im selben Kontext (Top-Level vs. iFrame, Produktions-Domain vs. Staging)
- Wenn Sie das Login einbetten, prüfen Sie, ob die Permissions-Policy konfiguriert ist (zum Beispiel `publickey-credentials-create` / `publickey-credentials-get`): [MDN Permissions-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy/publickey-credentials-create)
- Validieren Sie Ihre Domain-Strategie
- Wenn Sie iFrames nutzen, prüfen Sie die Feature-Policies

Sobald der `SecurityError` gelöst ist, sind die nächsten wichtigen Fehler `InvalidStateError`, `ConstraintError` und `DataError`, die oft auf Implementierungsfehler hindeuten.

## 6. InvalidStateError, ConstraintError, DataError: Als Implementierungs-Bugs behandeln

Diese Fehler sollten in einer reifen Passkey-Implementierung selten sein. Wenn sie auftreten, weisen sie meist darauf hin, dass die Optionsgenerierung für ein Segment fehlerhaft ist oder sich der Flow im falschen Zustand befindet.

### 6.1 InvalidStateError: "credentials already registered with the relying party"

**Was Sie in der Browser-Konsole sehen werden:**

| **Quelle**     | **Fehlermeldung**                                                                                                                                    |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Safari, WebKit | `InvalidStateError: The user attempted to register an authenticator that contains one of the credentials already registered with the relying party.` |
| Chrome, Edge   | `InvalidStateError: At least one credential matches an entry of the excludeCredentials list in the platform attached authenticator.`                 |
| Chrome, Edge   | `InvalidStateError: A request is already pending.`                                                                                                   |
| Firefox        | `InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable`                                                       |

Typische Bedeutungen:

- Registrierung: Sie haben versucht, ein Credential zu erstellen, das bereits existiert (Duplikat)
- Login: weniger häufig; bedeutet oft, dass der Ablauf/Zustand für die Plattform inkonsistent ist

Praktische Handhabung:

- Wenn es bei manueller Registrierung passiert, behandeln Sie es als "bereits registriert" und leiten Sie entsprechend weiter
- Stellen Sie sicher, dass `excludeCredentials` alle existierenden Credential-IDs für den Nutzer auflistet, damit der Authenticator Duplikate erkennen kann
- Bei Conditional Create ist ein `InvalidStateError` erwartet und sollte lautlos ignoriert werden: Es bedeutet, dass bereits ein Passkey im Provider existiert. Dasselbe gilt für `NotAllowedError` und `AbortError` bei Conditional Create (siehe [Conditional Create on Chrome](https://developer.chrome.com/docs/identity/webauthn-conditional-create))

### 6.2 ConstraintError

Typische Bedeutung: Der Authenticator kann die angeforderten Einschränkungen nicht erfüllen.

Häufige Auslöser:

- Fehlende Bildschirmsperre am Gerät (besonders bei Android): Die Plattform verlangt eine biometrische oder PIN-Verifikation, aber das Gerät hat keinen Lockscreen konfiguriert
- Zu strenge Anforderungen für `authenticatorAttachment` oder Resident Keys
- Harte `userVerification`-Anforderungen in Segmenten, in denen diese nicht verfügbar sind

Behebung: Einschränkungen lockern (sofern akzeptabel) oder einen alternativen Weg anbieten. Bei einer fehlenden Bildschirmsperre sollten Sie diese Bedingung erkennen und den Nutzer anleiten, anstatt stillschweigend zu scheitern (Android).

### 6.3 DataError

Typische Bedeutung: Eingaben sind fehlerhaft oder inkonsistent.

Häufige Auslöser:

- Kodierungsfehler (Base64 vs. Base64url)
- Ungültige Formate für Credential-IDs / Challenges

Behebung: Validieren und normalisieren Sie Eingaben an der Schnittstelle, an der Sie die WebAuthn-Optionen generieren. In der Praxis ist ein `DataError` in reifen Systemen praktisch nicht vorhanden – wenn Ihre Optionsgenerierung getestet ist, werden Sie dies nicht in Dashboards sehen.

Wenn diese Fehler unter Kontrolle sind, stellt sich als Nächstes die Frage nach der Abdeckung: Scheitern Nutzer, weil die Umgebung WebAuthn nicht auf die von Ihnen erwartete Weise ausführen kann?

## 7. NotSupportedError: The user agent does not support public key credentials

Ein `NotSupportedError` ist ein Signal für Abdeckung, nicht für Zuverlässigkeit. Es bedeutet meist, dass ein Segment nicht in der Lage ist, die Anfrage auszuführen (OS/Browser zu alt, fehlende Funktion, Feature nicht aktiviert).

**Was Sie in der Browser-Konsole sehen werden:**

| **Quelle**            | **Fehlermeldung**                                                                              |
| --------------------- | ---------------------------------------------------------------------------------------------- |
| Chrome, Edge          | `NotSupportedError: The user agent does not support public key credentials.`                   |
| Firefox               | `NotSupportedError: Resident credentials or empty 'allowCredentials' lists are not supported.` |
| Chrome, Edge, Firefox | `TypeError: PublicKeyCredential.parseCreationOptionsFromJSON is not a function`                |
| Chrome, Edge, Firefox | `TypeError: PublicKeyCredential.parseRequestOptionsFromJSON is not a function`                 |
| Chrome, Edge, Firefox | `TypeError: credential.toJSON is not a function`                                               |
| Safari                | `TypeError: Can only call PublicKeyCredential.toJSON on instances of PublicKeyCredential`      |

Die ersten beiden sind echte `NotSupportedError` DOMExceptions. Die Einträge unter `TypeError` sind technisch gesehen ein anderer Ausnahmetyp, repräsentieren aber dieselbe Fehlerklasse: Der Browser oder die Umgebung unterstützt das Angeforderte nicht. Die JSON-Serialisierungs-Familie der `TypeError` ist in der Praxis deutlich häufiger als die `NotSupportedError` DOMException selbst (siehe unten).

Häufige Ursachen sind:

- Ältere Browser/OS-Versionen, die grundsätzliches WebAuthn nicht unterstützen
- Anfordern von WebAuthn-Features, die auf dieser Plattform nicht verfügbar sind
- Versuch, plattformspezifische Flows auf nicht unterstützten Geräten auszuführen

**Die JSON-Serialisierungs-Familie ist die größte Quelle für `NotSupportedError`-Fehler in Produktion.** Technisch gesehen treten diese als `TypeError` (fehlende Methode) auf und nicht als `DOMException`, aber hier werden Sie ihnen begegnen. Es gibt zwei verschiedene Ursachen:

1. **Browser unterstützt die WebAuthn JSON-Serialisierungsmethoden nicht.** Der Browser verfügt über `navigator.credentials`, aber nicht über `PublicKeyCredential.parseCreationOptionsFromJSON` / `parseRequestOptionsFromJSON`. Dies macht etwa 90 % dieser Fehlerfamilie aus und konzentriert sich auf ältere Versionen von Safari und Chrome. Wenn Ihre Client-Bibliothek auf diese Methoden angewiesen ist, ohne einen Fallback anzubieten, erzeugt dies ein erhebliches Fehlervolumen.
2. **Passwort-Manager-Erweiterungen brechen `.toJSON()`.** Erweiterungen wie Bitwarden, LastPass oder 1Password können die Zeremonie abfangen und ein Objekt zurückgeben, das wie ein Credential aussieht, aber keine echte `PublicKeyCredential`-Instanz ist. Der Aufruf von `.toJSON()` darauf wirft entweder einen Fehler, gibt undefined zurück, oder das Objekt ist komplett `null`. Dies betrifft etwa 10 % der Familie, ist jedoch besonders schwer zu debuggen, da sich die Fehlermeldungen je nach Browser unterscheiden (Safari: "Can only call on instances of PublicKeyCredential"; Firefox: "does not implement interface PublicKeyCredential").

Die Handhabung sollte direkt und schnell sein:

- Sofort auf Passwort/OTP-Fallback ausweichen
- Segment erfassen, um Lücken in der Abdeckung zu quantifizieren
- Keine Passkey-CTAs in Segmenten anzeigen, die konsequent fehlschlagen

Wenn die Abdeckung in Ordnung scheint, Fehler aber dennoch in bestimmten Segmenten auftreten, haben Sie es möglicherweise mit Problemen auf Plattform-Ebene zu tun, die als `UnknownError` in Erscheinung treten.

## 8. UnknownError: An unknown error occurred while talking to the credential manager

Ein `UnknownError` ist ein Sammelbegriff für Fehler des Authenticators/OS, die nicht sauber in die anderen Kategorien passen. Er ist oft vorübergehend, kann aber auch nach OS-Updates vermehrt auftreten.

**Was Sie in der Browser-Konsole sehen werden:**

| **Quelle**         | **Fehlermeldung**                                                                                                                       |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| Chrome (Android)   | `UnknownError: An unknown error occurred while talking to the credential manager.`                                                      |
| Jeder Browser      | `UnknownError: The operation failed for an unknown transient reason.`                                                                   |
| Jeder Browser      | `UnknownError: Either the device has received unexpected request data, or the device has been reconfigured since the request was made.` |
| Jeder Browser      | `UnknownError: Something went wrong.`                                                                                                   |
| Chrome (LastPass)  | `TypeError: Cannot use 'in' operator to search for 'type' in null`                                                                      |
| Safari (LastPass)  | `TypeError: null is not an Object. (evaluating 'key in input')`                                                                         |
| Chrome (Bitwarden) | `FallbackRequested`                                                                                                                     |

Praktische Handhabung:

- Nutzen Sie eine retry-freundliche UX (nicht "dem Nutzer die Schuld geben")
- Erfassen Sie OS/Build-Nummern und den Kontext des Credential-Managers/Anbieters, wo möglich
- Achten Sie auf segmentspezifische Spitzen nach OS-Updates

Eine besondere Fehlerquelle, die nicht sauber in eine `DOMException`-Kategorie passt: **Passwort-Manager-Browsererweiterungen** (wie Bitwarden, LastPass, 1Password und andere) können WebAuthn-API-Aufrufe abfangen und nicht-standardkonforme Antworten zurückgeben. Auch wenn diese im Vergleich zu Nutzerabbrüchen nur in geringem Umfang auftreten, lohnt es sich, sie zu tracken, da sie bestimmte Nutzersegmente beständig betreffen und die Symptome verwirrend sind: fehlende Methoden auf dem zurückgegebenen Credential-Objekt, unerwartete Fehlertypen oder fehlerhafte Antworten, die keinem dokumentierten WebAuthn-Fehler entsprechen. Diese treten oft als `UnknownError` oder unklassifizierte Ausnahmen in Erscheinung. Wenn Sie Fehlerspitzen bemerken, die sich auf bestimmte Browser konzentrieren, ohne dass es eine Erklärung auf OS-Ebene gibt, prüfen Sie, ob eine Credential-Manager-Erweiterung beteiligt ist.

Bislang haben wir Browser-Fehlernamen behandelt. Aber wenn Sie auch native Apps ausliefern, sieht die Fehlerlandschaft anders aus – und in mancher Hinsicht deutlich besser.

## 9. Ein Wort zu nativen Apps (iOS und Android)

Alles bisherige bezieht sich auf Webbrowser. Native Apps – iOS mit dem ASAuthorization-Framework, Android mit dem Credential Manager – teilen sich die gleichen grundlegenden Fehlerkategorien, unterscheiden sich aber in wichtigen Aspekten:

1. **"Keine Credentials" ist ein klares Signal.** Im Web fassen Browser aus Datenschutzgründen "Kein Credential verfügbar" und "Nutzer hat abgebrochen" im `NotAllowedError` zusammen. Nativ können Sie durch `preferImmediatelyAvailableCredentials` bei iOS (`ASAuthorizationController`) oder `setPreferImmediatelyAvailableCredentials(true)` bei Android (`GetCredentialRequest`) dem OS mitteilen, dass nur bereits auf dem Gerät vorhandene Credentials angeboten werden sollen und sofort abgebrochen wird, falls keine existieren. Dies liefert eine klare "Keine Credentials"-Antwort, die im Web nicht möglich ist.

2. **Status des Credential-Providers ist sichtbar.** Native Plattformen können Ihnen unter Umständen mitteilen, wenn kein Credential-Provider (Google Password Manager, iCloud Keychain, 1Password etc.) installiert, konfiguriert oder als Standard festgelegt ist, sodass Sie darauf reagieren können. Im Web sind diese Informationen hinter undurchsichtigen `NotAllowedError`-Meldungen verborgen.

3. **Fehlermeldungen sind spezifischer.** Weil der Nutzer die App installiert hat – und damit eine Vertrauensbeziehung zur Relying Party aufgebaut hat – gibt das Betriebssystem mehr diagnostische Details preis. Die Datenschutzbedenken, die Browser dazu zwingen, vage zu bleiben, greifen nicht in gleicher Weise, wenn die App bereits auf dem Gerät ist. iOS liefert lokalisierte Nachrichten in der Gerätesprache des Nutzers. Android liefert strukturierte Fehlertypen mit Ursachenketten. Das erleichtert das Debugging, bedeutet aber, dass Ihre Fehlerbehandlung Lokalisierung und plattformspezifische Fehlerformate berücksichtigen muss.

### 9.1 iOS (ASAuthorization Framework)

iOS stellt Passkey-Fehler über das ASAuthorization-Framework bereit. Alle Fehler kommen im `authorizationController(controller:didCompleteWithError:)`-Delegate-Callback als `NSError`-Objekte an.

**Klassifizieren Sie nach Domain + Code, nicht nach dem Nachrichten-String.** Die primäre Fehler-Domain ist `com.apple.AuthenticationServices.AuthorizationError` (`ASAuthorizationError.errorDomain`). Casten Sie den Fehler mit `let nsError = error as NSError` und gleichen Sie `.domain` und `.code` ab. Nutzen Sie in Produktion niemals `.localizedDescription` für Vergleiche – Apples Nachrichten sind in über 30 Sprachen lokalisiert und können sich in neuen OS-Versionen ändern. Die unten aufgelisteten Meldungen sind nützlich, um Fehler in Logs zu erkennen, nicht aber als Kriterium zur Klassifizierung.

**Öffentliche ASAuthorizationError Codes:**

| **Code** | **Name**                                | **Seit** | **Bedeutung**                                                                                                                                                                                                                                                                                                               |
| -------- | --------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1000     | `Unknown`                               | iOS 13   | Sollte nicht in Produktion auftreten. Allgemeiner Sammel-Fehler.                                                                                                                                                                                                                                                            |
| 1001     | `Canceled`                              | iOS 13   | Nutzer hat den Passkey-Dialog geschlossen. Häufigster Fehler insgesamt - das Äquivalent zum `NotAllowedError`. Klares Signal mit leerem `userInfo` und ohne zugrundeliegenden Fehler.                                                                                                                                       |
| 1002     | `InvalidResponse`                       | iOS 13   | Korruption auf Framework-Ebene. In der Praxis selten.                                                                                                                                                                                                                                                                       |
| 1003     | `NotHandled`                            | iOS 13   | Kein Provider hat die Anfrage bearbeitet. Prüfen Sie Berechtigungen und die Konfiguration des Credential-Providers.                                                                                                                                                                                                         |
| 1004     | `Failed`                                | iOS 13   | Genereller Fehlschlag. `localizedDescription` enthält den tatsächlichen Grund (z. B. "Application with identifier X is not associated with domain Y"). `userInfo` kann einen `FailureReason`-String enthalten, aber `NSUnderlyingErrorKey` ist nicht immer befüllt.                                                       |
| 1005     | `NotInteractive`                        | iOS 15   | Keine Credentials verfügbar bei der Nutzung von `preferImmediatelyAvailableCredentials`. Das ist das klare "Nicht gefunden"-Signal - das iOS-Äquivalent für "Auf diesem Gerät existiert kein Passkey". Es wurde keine UI angezeigt.                                                                                           |
| 1006     | `MatchedExcludedCredential`             | iOS 18   | Für diese RP existiert bereits ein Passkey auf diesem Gerät. Klares Signal zur Erkennung von Duplikaten - leeres `userInfo`, kein `NSUnderlyingErrorKey`. Die Klassifizierung funktioniert ohne String-Abgleich.                                                                                                            |
| 1007     | `CredentialImport`                      | iOS 18.2 | Credential-Import fehlgeschlagen.                                                                                                                                                                                                                                                                                           |
| 1008     | `CredentialExport`                      | iOS 18.2 | Credential-Export fehlgeschlagen.                                                                                                                                                                                                                                                                                           |
| 1009     | `PreferSignInWithApple`                 | iOS 26   | Nutzer bevorzugt Sign in with Apple anstelle von Passkey. Neu in iOS 26.                                                                                                                                                                                                                                                    |
| 1010     | `DeviceNotConfiguredForPasskeyCreation` | iOS 26   | Dem Gerät fehlt der Passcode oder die iCloud-Keychain-Konfiguration. Bekannter iOS 26 Simulator-Bug: gibt 1010 zurück, auch wenn die Konfiguration korrekt ist (reproduziert sich nicht auf echten Geräten).                                                                                                                |

Der wichtigste Unterschied für die Produktion: **Seit iOS 18 geben duplizierte Credentials ihren eigenen Fehlercode 1006 (`MatchedExcludedCredential`) zurück.** Bei iOS 17 und älter waren Duplikate unter dem Code 1004 (`Failed`) verborgen. Ab iOS 18 ist die Unterscheidung strukturell (anderer Fehlercode), nicht textbasiert.

**Häufige Laufzeitfehler (Referenz auf Log-Ebene):**

Diese Nachrichten erscheinen in `localizedDescription` oder in `userInfo` für spezifische Fehler-Szenarien. Nutzen Sie sie für die Log-Suche und das Debugging, nicht für die programmatische Klassifizierung.

| **Nachricht (Englisches Locale)**                                               | **Zugrundeliegender Code** | **Hinweise**                                                                                                                                                            |
| ------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Application with identifier <TeamID.BundleID> is not associated with domain X` | 1004 (`Failed`)            | Die Associated Domains-Berechtigung der App passt nicht zur Relying Party. Fixen Sie die `apple-app-site-association`-Datei auf Ihrem Server.                           |
| `Couldn't communicate with a helper application.`                               | 1004 (`Failed`)            | Die Credential-Provider-Extension antwortete nicht. Temporär - ein erneuter Versuch ist angemessen.                                                                     |
| `Request already in progress for specified application identifier.`             | 1004 (`Failed`)            | Ein doppelter ASAuthorization-Request wurde ausgelöst, während ein anderer noch lief. Race Condition in der App.                                                        |
| `Stolen Device Protection is enabled and biometry is required.`                 | 1004 (`Failed`)            | iOS 17+ Stolen Device Protection blockiert biometrische Auth an unbekannten Orten. Für Entwickler nicht lösbar, aber es lohnt sich, dies dem Nutzer anzuzeigen.         |
| `(AuthenticationServicesCore.ASCABLEClient.ClientError error 2.)`               | Eigene Domain              | Bluetooth-Handshake für Cross-Device Authentication (Hybrid/CABLE) ist fehlgeschlagen.                                                                                  |
| `(AuthenticationServicesCore.ASCABLEClient.ClientError error 3.)`               | Eigene Domain              | Bluetooth-Verbindung für Cross-Device Authentication ist fehlgeschlagen.                                                                                                |

**Lokalisierte "Keine Credentials"-Nachrichten (Code 1005):**

Wenn `preferImmediatelyAvailableCredentials` gesetzt ist und kein Passkey existiert, gibt iOS Code 1005 (`NotInteractive`) mit einer lokalisierten Meldung in der Gerätesprache des Nutzers zurück. Dies ist einzigartig für native Apps – Webbrowser stellen dieses Signal nie zur Verfügung. Die Nachricht beginnt immer mit `The operation couldn't be completed.`, gefolgt von dem lokalisierten Text:

| **Sprache**           | **Nachricht**                                                                        |
| --------------------- | ------------------------------------------------------------------------------------ |
| Chinesisch (Verein.)  | `没有可用于登录的凭证。`                                                             |
| Vietnamesisch         | `Không có sẵn thông tin để đăng nhập.`                                               |
| Arabisch              | `لا تتوفر بيانات اعتماد لتسجيل الدخول.`                                              |
| Spanisch              | `No hay ninguna credencial disponible para iniciar sesión.`                          |
| Chinesisch (Tradit.)  | `沒有可用於登入的憑證。`                                                             |
| Koreanisch            | `로그인을 위한 자격 증명이 없습니다.`                                                |
| Französisch (Kanada)  | `Aucun identifiant disponible pour la connexion.`                                    |
| Portugiesisch (Bras.) | `Nenhuma credencial disponível para login.`                                          |
| Französisch (Frank.)  | `Aucune information d'identification n'est disponible pour procéder à la connexion.` |
| Thai                  | `ไม่มีข้อมูลประจำตัวสำหรับเข้าสู่ระบบ`                                               |
| Italienisch           | `Non ci sono credenziali disponibili per l'accesso.`                                 |
| Niederländisch        | `Geen inloggegevens beschikbaar.`                                                    |
| Japanisch             | `ログイン用の資格情報がありません。`                                                 |
| Türkisch              | `Oturum açmak için kullanılabilecek kimlik bilgisi yok.`                             |
| Deutsch               | `Keine Anmeldedaten verfügbar.` *(Hinweis für den Leser)*                            |

*(Beachten Sie, dass im obigen originalen Text keine deutsche Version stand, aber die Logik auf Code 1005 greift.)*

Auf englisch-lokalisierten Geräten wird das Problem "Keine Credentials" normalerweise schon auf API-Ebene geklärt, bevor das ASAuthorization-Framework einen lokalisierten Fehler zurückgibt, weshalb dort keine englische Variante erscheint. Gleichen Sie programmgesteuert immer den Code 1005 ab, anstatt diese Strings zu analysieren.

### 9.2 Android (Credential Manager API)

Android liefert Passkey-Fehler über die Credential Manager API (`androidx.credentials`). Die Fehlermeldungen beinhalten eine Hauptmeldung und oft eine `cause` mit zusätzlichen Details. Im Vergleich zu iOS bietet Android strukturiertere Fehlertypen und explizitere Ursachen für Konfigurationsprobleme.

**Nutzerabbruch und Credential-Erkennung:**

| **Fehler**                                        | **Hinweise**                                                                                                                                                                                                       |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `User cancelled the operation`                    | Nutzer hat den Passkey-Prompt geschlossen. Das Äquivalent zum `NotAllowedError`. Hinweis: Der Credential Manager gibt über einen anderen Pfad auch `User canceled the request` zurück - beides ist identisch.      |
| `Excluded credential matches existing credential` | Ein Passkey existiert bereits für diese Credential-ID. Das Äquivalent zum `InvalidStateError`. Im Gegensatz zu iOS unterscheidet sich die Nachricht vom Nutzerabbruch.                                             |
| `No create options available.`                    | Kein geeigneter Credential-Provider kann die Erstellungsanfrage bearbeiten. Bedeutet meist, dass die Google Play Services veraltet sind oder kein Credential-Provider die Erstellung von Passkeys unterstützt.     |

**Konfigurations- und Sicherheitsfehler:**

| **Fehler**                                                                     | **Hinweise**                                                                                                                                        |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Passkeys not supported for this app`                                          | Digital Asset Links (`assetlinks.json`) fehlt oder enthält den Fingerprint des Signaturzertifikats der App nicht. Das Äquivalent zum `SecurityError`. |
| `Https failed: respCode=301, url=https://<domain>/.well-known/assetlinks.json` | Die Datei `assetlinks.json` gibt einen Redirect statt HTTP 200 zurück. Android verlangt die Datei genau an der URL ohne Redirects.                  |
| `The incoming request cannot be validated`                                     | Der Credential Manager kann den Request nicht mit den Digital Asset Links validieren.                                                               |
| `RP ID cannot be validated.`                                                   | Die Relying-Party-ID in den WebAuthn-Optionen passt nicht zur `assetlinks.json`.                                                                    |
| `Screen lock is missing.`                                                      | Keine PIN, Muster oder Biometrie auf dem Gerät konfiguriert. Passkeys erfordern eine Nutzerverifikation. Das Äquivalent zum `ConstraintError`.      |
| `Cannot find an eligible account.`                                             | Kein Google-Account auf dem Gerät ist berechtigt für die Passkey-Erstellung (selten, typisch für eigene Enterprise-Setups).                         |

**Plattform- und Authenticator-Fehler:**

| **Fehler**                                                                               | **Hinweise**                                                                                                                                                                                                                                         |
| ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Unsuccessful result from folsom activity.`                                              | Interner Fehler bei Google Play Services. "Folsom" ist eine GMS-Komponente für Passkey-Operationen. Temporär - erneuter Versuch sinnvoll.                                                                                                            |
| `Can't find the proper key to decrypt the private key from WebauthnCredentialSpecifics.` | Ein synchronisierter Passkey existiert, aber das Gerät kann den privaten Schlüssel nicht entschlüsseln. Der Status im Google Password Manager ist inkonsistent. Handlungsbedarf durch Entwickler nicht möglich.                                      |
| `Operation was interrupted` (cause: `The UI was interrupted - please try again.`)        | Die Credential-Manager-UI wurde von einer anderen Activity unterbrochen (eingehender Anruf, Bildschirmdrehung, App im Hintergrund). Das Äquivalent zum `AbortError`.                                                                                 |
| `Unknown credential error`                                                               | Generischer Fehler, wenn kein spezifischer Fehlertyp zutrifft. Typischerweise vorübergehend.                                                                                                                                                         |
| `timeout` (cause: `Canceled`)                                                            | Die Credential-Manager-Operation ist abgelaufen, bevor der Nutzer die biometrische Überprüfung abgeschlossen hat.                                                                                                                                    |

## 10. Alles zusammenfügen: Die Fehler-Taxonomie

Das folgende Diagramm zeigt, wie alle diskutierten Ebenen – Infrastruktur, Umgebung, Operationstyp, Klassifizierung und Erkennung – end-to-end zusammenwirken. Es ist das mentale Modell, das Sie im Kopf haben sollten, wenn Sie Ihr Fehler-Tracking entwerfen.

```mermaid
flowchart TD
    %% Global Styles
    classDef expected fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;
    classDef unexpected fill:#ffebee,stroke:#c62828,stroke-width:2px;
    classDef network fill:#fff3e0,stroke:#ef6c00,stroke-dasharray: 5 5;
    classDef env fill:#f3e5f5,stroke:#7b1fa2,stroke-width:1px;
    classDef action fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;

    %% --- LEFT SIDE: NETWORK & SERVER ---
    subgraph Infrastructure ["Infrastruktur (Server/Netzwerk)"]
        direction TB
        ServerErr["Serverseitiger Fehler<br/>500 / Logikfehler"]:::network
        NetErr["Netzwerkfehler<br/>Timeout / 400 Bad Request"]:::network

        ServerErr & NetErr -->|Äußert sich als| ClientManifest["Clientseitiger generischer Fehler"]
    end

    %% --- CENTER: THE ENVIRONMENT STACK (From Sketch) ---
    subgraph Environment ["Die Umgebung (Clientseitig)"]
        direction TB

        %% Layer 1: Platform Type
        subgraph Type ["Ebene 1: Plattform"]
            Web["Web / Browser"]
            Native["Nativ / App"]
        end

        %% Layer 2: OS Context
        subgraph OS_Layer ["Ebene 2: OS & Version"]
            OS_Web["OS: Windows, macOS, Linux"]
            OS_Nat["OS: iOS, Android"]
            OS_Ver["OS Version / Einstellungen<br/>(Bildschirmsperre, Biometrie)"]

            Web --> OS_Web
            Native --> OS_Nat
            OS_Web & OS_Nat --> OS_Ver
        end

        %% Layer 3: Client Software
        subgraph Client_Layer ["Ebene 3: Client-Software"]
            Browser["Browser: Chrome, Safari, Edge<br/>+ Version"]
            App["Native App / WebView<br/>+ App-Version"]

            OS_Ver --> Browser
            OS_Ver --> App
        end

        %% Layer 4: WebAuthn Operation
        subgraph Op_Layer ["Ebene 4: WebAuthn Operation"]
            OpType{"Operationstyp"}

            Login["Login<br/>(navigator.credentials.get)"]
            Reg["Registrierung<br/>(navigator.credentials.create)"]

            Browser & App --> OpType
            OpType --> Login
            OpType --> Reg
        end

        %% Layer 5: Sub-types & Complexity
        subgraph Modality ["Ebene 5: Modalität & Komplexität"]
            Sub_CUI["CUI / Conditional UI"]
            Sub_Auto["Automatische Operation"]
            Sub_CDA["CDA / Cross-Device Auth"]

            Login & Reg --> Sub_CUI
            Login & Reg --> Sub_Auto
            Login & Reg --> Sub_CDA
        end
    end

    %% --- BOTTOM: CLASSIFICATION & ACTION (The "What here?" section) ---
    subgraph Analysis ["Fehleranalyse & Laufzeit"]
        direction TB

        %% Classification
        Classification{"Klassifizierung"}

        Exp["Erwarteter Fehler<br/>(Nutzer brach Zeremonie ab)"]:::expected
        Unexp["Unerwarteter Fehler<br/>(System/Absturz/Unbekannt)"]:::unexpected

        ClientManifest --> Classification
        Sub_CUI & Sub_Auto & Sub_CDA --> Classification

        Classification --> Exp
        Classification --> Unexp

        %% Detection Logic
        subgraph Detection ["Erkennungsziele"]
            P1["P1: Login-Probleme"]
            P2["P2: Erstellungs-Probleme"]
            Baseline["Baseline Drift erkennen<br/>(Anstieg erwarteter Fehler)"]
            NewErr["Neue Anomalien erkennen<br/>(Anstieg unerwarteter Fehler)"]
        end

        Exp --> Baseline
        Unexp --> NewErr
        Exp & Unexp --> P1 & P2

        %% Actionable Outcomes
        subgraph Action ["Maßnahmen zur Behebung"]
            Fix["Hotfix ausrollen / Neue Version"]:::action
            Fallback["Automatischen Fallback aktivieren<br/>(Passkey deaktivieren)"]:::action
        end

        P1 & P2 & NewErr --> Fix
        P1 & P2 & NewErr --> Fallback
    end

    %% Connectors
    Infrastructure -.-> Environment
```

Die zentrale Erkenntnis: Ein roher `error.name` ergibt erst dann einen Sinn, wenn Sie wissen, welche Ebene der Umgebung ihn erzeugt hat, welche Operation lief und ob der Fehler erwartet oder unerwartet war. Die folgenden Abschnitte behandeln, was zu protokollieren ist und wie man darauf reagiert.

## 11. Was zu erfassen ist, damit Fehler debuggbar werden

Die meisten Fehlerklassifizierungen in diesem Artikel können allein mit clientseitigen Signalen erfolgen. Ein Frontend-only Observability-SDK erfasst ausreichend Kontext, um die große Mehrheit an WebAuthn-Fehlern zu klassifizieren. Auf diese Weise ist auch das Corbado Observability SDK aufgebaut: Die clientseitige Ebene kümmert sich um Fehlerzuordnung, Timing, Operationskontext und Plattformerfassung. Das serverseitige Logging fügt eine zweite Ebene für Fehler hinzu, die nur das Backend erkennen kann.

Die wesentliche Anforderung: Jeder Versuch muss durchgehend (end-to-end) verknüpfbar sein. Eine gemeinsame Korrelations-ID (z. B. `auth_flow_id`) verbindet den clientseitigen Kontext mit dem Ausgang der Serververifizierung.

### 11.1 Clientseitige Signale (Frontend SDK)

| **Signal**                                       | **Warum es wichtig ist**                                                                                                                                            |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `error.name` + normalisierte Kategorie-Bezeichn. | Roher Browserfehler + Ihre Klassifizierung                                                                                                                          |
| Operationstyp                                    | Conditional UI, modaler Login, manuelles Create, Conditional Create, Auto-Append. **CDA (Cross-Device Auth)** ist ein eigenes, komplexes Thema.                     |
| Vollständiger Umgebungskontext                   | OS + Version, Browser + Version, **Hardware-Marke/Modell**, **Authenticator-Einstellungen** (z. B. GPM aktiv?)                                                      |
| Kontext von Authenticator/Credential Manager     | Probleme mit Erweiterungen und Anbietern                                                                                                                            |
| Time-to-Error seit dem Start der Operation       | Sofortige Ablehnung (`<1s`) vs. Nutzerabbruch (1-15s) vs. Timeout (30s+)                                                                                            |
| Netzwerk-/Verbindungsstatus                      | Netzwerkfehler äußern sich oft als Client-Fehler. Erfassen Sie, ob der Nutzer offline war, und **stellen Sie Logs in eine Warteschlange**, bis die Verbindung steht. |
| Ob QR/Hybrid-UI erschien                         | Lokaler vs. Cross-Device-Fehler                                                                                                                                     |
| Korrelations-ID (`auth_flow_id`)                 | Zusammenführen mit Server-Logs                                                                                                                                      |

### 11.2 Serverseitige Signale (Backend-Verifizierung)

Server-Verifizierungsfehler treten auf, nachdem der Browser ein Credential und eine signierte Challenge zurückgegeben hat. Dies sollten strukturierte Fehler mit expliziten Codes sein und nicht mit den clientseitigen `DOMException`-Namen in einen Topf geworfen werden.

| **Signal**                                           | **Warum es wichtig ist**                                                                                                                                                                                                      |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Challenge unpassend / abgelaufen                     | Probleme mit Session-Timing oder Replay-Angriffen                                                                                                                                                                             |
| Origin / RP-ID passt nicht                           | Konfigurationsbugs in Multi-Domain-Setups                                                                                                                                                                                     |
| Ungültige Signatur / Credential nicht gefunden       | Gelöschtes oder defektes Credential. Häufiger Fall: Conditional UI Login mit einem Passkey, den der Nutzer serverseitig bereits gelöscht hat. Nutzen Sie die Signal-API, um Credential-Listen von Client und Server synchron zu halten. |
| User Handle passt nicht                              | Account-Mapping-Probleme                                                                                                                                                                                                      |
| Korrelations-ID (`auth_flow_id`)                     | Zusammenführen mit clientseitigem Kontext                                                                                                                                                                                     |

[Watch on YouTube](https://www.youtube.com/watch?v=wnrXJzvBjsU)

Liegen diese Daten vor, wird die Schlussfolgerung einfach: Die meisten "Fehler" stellen sich als UX-Fixes, Abdeckungs-Fixes oder Konfigurations-Fixes heraus. Die Erstellung und Pflege einer solchen Klassifizierung in Eigenregie bedeutet jedoch einen erheblichen, dauerhaften Aufwand.

## 12. Über Fehlernamen hinaus: Wie Corbado rohe Fehler in handlungsrelevante Signale wandelt

Die obige Logging-Checkliste erfasst Rohdaten. In einer produktiven, großen Umgebung reicht `error.name` allein nicht aus. Diese Klassifizierung selbst zu entwickeln, bedeutet stetige Arbeit: Fehlermeldungen ändern sich mit jeder neuen Browser- und OS-Version, Passwort-Manager-Anbieter liefern Updates, die das Zeremonie-Verhalten verändern, und neue Fehlersignaturen tauchen mit jedem Feature-Launch auf.

### 12.1 Warum `error.name` allein nicht ausreicht

Derselbe `NotAllowedError` kann sechs verschiedene Ursachen haben, basierend auf drei Dimensionen, die Browser nicht für Sie auftrennen:

| **Dimension**                | **Was der Browser liefert** | **Was Sie tatsächlich benötigen**                                                                  | **Beispiel**                                                                                                        |
| ---------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **Operationskontext**        | `NotAllowedError`           | War es Conditional UI, ein modaler Login, manuelles Create, Conditional Create oder ein Auto-Append? | Android gibt denselben "unknown error" für einen abgebrochenen Login (erwartet) und einen Erstellungsfehler (unerwartet) zurück |
| **Timing**                   | Keine Zeitangabe            | Sofort (`<1s`) vs. Nutzerabbruch (1-15s) vs. Timeout (30s+)                                        | 200ms = Umgebungsablehnung; 5s = Nutzer hat Dialog gesehen und abgebrochen; 35s = Timeout                           |
| **Plattform + Authenticator** | Generischer `error.name`    | OS, Browser, Version, Credential Manager für jeden Fehler                                          | "Nutzer hat Dialog in Chrome geschlossen" und "Autofill in Safari nicht verfügbar" enden beide als `NotAllowedError` |

### 12.2 Was Corbados Observability SDK erfasst

Genau für dieses Problem wurde das [Corbado Observability SDK](https://www.corbado.com/pricing) entwickelt. Es ist eine leichtgewichtige Frontend-Integration, die sich auf Ihre bestehende Passkey-Implementierung aufsetzt, mit jedem WebAuthn-Server und IDP funktioniert und automatisch jeden WebAuthn-Fehler entlang aller drei Dimensionen klassifiziert:

| **Funktion**                          | **Was sie macht**                                                                                                                                                                                                                                                                      |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Fehlerzuweisung**                   | Erfasst bei jedem Zeremonie-Versuch OS, OS-Version, Browser, Browser-Version und Authenticator                                                                                                                                                                                         |
| **Operationsmodus**                   | Verknüpft jeden Fehler mit der spezifischen Operation (Conditional UI, modaler Login, manuelles Create, Conditional Create, Auto-Append), sodass derselbe `NotAllowedError` auf verschiedene Ursachen zurückzuführen ist                                                               |
| **Timing seit Start der Aktion**      | Protokolliert die Dauer vom Start der Zeremonie, um sofortige Ablehnungen, Nutzerabbrüche und Timeouts zielsicher zu unterscheiden                                                                                                                                                     |
| **Intelligente Fehlerklassifizierung** | Analysiert den vollständigen Fehlerkontext (nicht nur den Namen) und normalisiert über diverse **Umgebungen** (OS, Hardware, Settings) hinweg. Unterscheidet **Erwartete (Nutzerabbruch)** von **Unerwarteten (Systemfehler)** Fehlern und priorisiert spezifische Gruppen wie **CDA** vs. Lokal. |
| **Passwort-Manager-Fragmentierung**   | Erkennt, wenn Credential-Manager-Erweiterungen (Bitwarden, 1Password, LastPass) Zeremonien abfangen und nicht-standardkonforme Antworten liefern, und trennt durch Erweiterungen bedingte Fehler von Plattformfehlern                                                                  |

Dies ist die **Observe**-Schicht: Sichtbarkeit auf das, was passiert, ohne Ihre Implementierung zu ändern.

### 12.3 Zwei Wege zum Debuggen: Top-Down und Bottom-Up

Die Corbado-Konsole unterstützt zwei Wege zur Problemanalyse:

**Top-down (Vom Dashboard zur Ursache):**

1. **Nach zwei Arten von Anomalien suchen:**
    - **Gestiegene Erwartete Fehler (Baseline Drift):** Hat eine spezifische Umgebung (z. B. iOS 18.2 auf iPhone 15) einen allmählichen Anstieg von "Nutzerabbrüchen" verzeichnet? Dies deutet oft auf eine neue UX-Reibung hin, die durch ein OS-Update eingeführt wurde.
    - **Gestiegene Unerwartete Fehler (Spikes):** Ein komplett neuer Fehler oder ein plötzlicher Anstieg an Fehlschlägen. Dies deutet meist auf eine Breaking Change (internes IDP-Update) oder eine Regression in einer neuen Browserversion hin.
2. **Nach Impact priorisieren:**
    - **P1: Login-Probleme.** Wenn die Login-Erfolgsraten fallen, sofort alarmieren.
    - **P2: Erstellungs-Probleme.** Trends beobachten, aber keine Entwickler wegen eines Anstiegs an "Nutzerabbrüchen" bei Erstellungen nachts wecken.
3. **In die Umgebung drillen:** Nutzen Sie die granularen Dimensionen (Hardware, Auth-Einstellungen), um einzugrenzen, ob das Problem global ist oder spezifisch für "Samsung-Geräte mit Android 14".
4. **Behebung:** Wenn ein kritischer Spike erkannt wird, haben Sie einen **Kill-Switch** bereit. Deaktivieren Sie Passkeys für diese spezifische Umgebung automatisch oder manuell und fallen Sie auf OTPs/Passwörter zurück, um die Login-Raten während der Untersuchung zu erhalten.

**Bottom-up (Von Fehlermustern zur Auswirkung):**

1. Starten Sie mit der Fehlerklassifizierungs-Ansicht. Prüfen Sie klassifizierte Fehlermuster und deren Volumen.
2. Verfeinern Sie Fehlerzuordnungen, sobald neue Muster auftauchen (z. B. eine neue Browserversion liefert eine veränderte Fehlermeldung).
3. Fehler werden mit KPI-Veränderungen korreliert und als Annotationen in Dashboards eingeblendet, sodass ein Spike in einem spezifischen Fehlermuster automatisch mit der Metrik verknüpft wird, die er beeinflusst hat.

Beide Pfade führen zusammen: Top-down sagt Ihnen, dass etwas nicht stimmt, Bottom-up verrät Ihnen warum. Der [AI Analytics Assistant](https://www.corbado.com/ai-analytics-assistant) verbindet die beiden, indem er Ihnen erlaubt, Fragen in natürlicher Sprache sowohl zu Fehlerdaten als auch zu Adoptionsmetriken zu stellen.

Teams, die auf diese Signale reagieren möchten, können zu **Adopt** wechseln. Dies fügt [Passkey-Intelligence](https://docs.corbado.com/corbado-connect/features/passkey-intelligence) hinzu, die Passkey-Angebote absichert, Prompts optimiert und fehlerhafte Passkey-Zustände repariert. Für regulierte Umgebungen gibt es **Enterprise**, was PSD2-konforme Konfigurationen und SIEM-Integration hinzufügt.

## 13. Fazit

WebAuthn-Fehlernamen sind kein endgültiges Urteil. Es sind Hinweise – und sie werden erst handlungsrelevant, wenn man sie mit dem Operationstyp, dem Timing und dem Plattform-Kontext verbindet.

- **Was bedeuten die häufigsten WebAuthn-Fehlernamen in der Produktion?** Die meisten lassen sich auf wenige Ebenen reduzieren: Kontrollfluss des Nutzers (`NotAllowedError`), App-Lifecycle/Concurrency (`AbortError`), Sicherheitskontext/Konfiguration (`SecurityError`) oder Options-/Zustandsfehler (`InvalidStateError`, `ConstraintError`, `DataError`). Das weitaus größte Volumen entfällt auf `NotAllowedError`, was in der Regel ein erwartetes Verhalten ist (Nutzer hat den Prompt geschlossen).
- **Wie disambiguiert man `NotAllowedError`?** Verwenden Sie Timing (sofortige Ablehnung vs. Nutzerabbruch vs. Timeout), einen QR/Hybrid-Indikator, Nutzeraktivierungs-Kontext (besonders auf iOS/Safari) und den Operationstyp (Conditional UI vs. modaler Login vs. Passkey-Erstellung vs. Conditional Create). Behandeln Sie nicht alle `NotAllowedError` als denselben Ausfallgrund.
- **Warum ist der Operationstyp wichtig?** Derselbe `error.name` ist während eines Conditional UI Logins ein völlig anderes Signal als während eines Conditional Create oder bei manueller Passkey-Erstellung. Den Operationstyp zusammen mit dem Fehler zu protokollieren, macht aus einem generischen `NotAllowedError` eine Kategorie, an der man ansetzen kann.
- **Welcher Mindestkontext macht Fehler debuggbar?** Erfassen Sie `error.name`, Operationstyp, Time-to-Error, Flow-Typ, ob QR/Hybrid-UI angezeigt wurde, OS/Browser/Gerät (inkl. Versionen), eine Korrelations-ID (`auth_flow_id`) sowie serverseitige Ablehnungsgründe als explizite Codes.

Zwei Faustregeln gelten für alle Fehlertypen: Zeigen Sie dem Nutzer niemals rohe Browserfehler an – bieten Sie stattdessen immer einen Fallback-Pfad an – und trennen Sie lokale Versuche von QR/Hybrid-Cross-Device-Versuchen, da diese aus unterschiedlichen Gründen fehlschlagen und unterschiedliche Fixes erfordern. Auf großer Skala ist die Pflege der Fehlerklassifizierung über alle Browser, OS-Versionen und Credential-Manager hinweg ständige Arbeit.

## Häufig gestellte Fragen (FAQ)

### Wie unterscheide ich, ob ein Nutzer einen Passkey-Prompt abbricht oder ob das Gerät keinen Passkey hat?

Im Web fassen Browser beide Fälle aus Datenschutzgründen als `NotAllowedError` zusammen, daher können Sie sie nicht direkt unterscheiden. Nutzen Sie das Timing als Hilfsmittel: Ein Fehler in unter 1 Sekunde bedeutet meist eine Ablehnung durch die Umgebung oder eine fehlende Funktion, während 1-15 Sekunden darauf hindeuten, dass der Nutzer den Dialog gesehen und geschlossen hat. Bei nativen iOS- und Android-Apps gibt Ihnen das Setzen von `preferImmediatelyAvailableCredentials` vor der Anfrage ein klares "Keine Anmeldedaten"-Signal (iOS Code 1005, Android `GetCredentialRequest`), bevor überhaupt eine UI angezeigt wird.

### Warum ist meine WebAuthn-Fehlerrate so hoch, obwohl Passkeys für die meisten Nutzer zu funktionieren scheinen?

In optimierten, großen Passkey-Implementierungen sind über 95 % der erfassten WebAuthn-Fehler erwartete Nutzerabbrüche, keine Systemausfälle. Das reine Tracking von `error.name`-Zählungen ohne die Trennung von "Nutzer hat Prompt geschlossen" und echten Fehlschlägen bläht Fehlermetriken auf und verdeckt echte Probleme. Unterteilen Sie Ihre Zählungen nach Operationstyp und behandeln Sie Nutzerabbruch-Kategorien getrennt von unerwarteten Fehlern wie `SecurityError`, `ConstraintError` und `DataError`.

### Was bedeutet der ASAuthorizationError Code 1005 bei iOS und wie sollte ich ihn nutzen?

Der iOS-Code 1005 (`NotInteractive`) bedeutet, dass kein Passkey auf dem Gerät verfügbar war, als `preferImmediatelyAvailableCredentials` beim `ASAuthorizationController` gesetzt wurde, und dass dem Nutzer keine UI angezeigt wurde. Dies ist das klare "Kein Passkey existiert auf diesem Gerät"-Signal, das Webbrowser aufgrund von Datenschutzvorgaben nicht bieten können. Klassifizieren Sie immer anhand des numerischen Codes, nicht anhand der `localizedDescription`, da Apples Nachrichten in über 30 Sprachen übersetzt sind und sich über OS-Versionen hinweg ändern können.

### Wie gehe ich mit NotAllowedError während eines Conditional Create oder auto-getriggerten Passkey-Appends um?

Während eines Conditional Create sind `NotAllowedError`, `AbortError` und `InvalidStateError` allesamt erwartete Ausgänge und sollten stillschweigend ignoriert werden, anstatt sie als Fehler darzustellen. Ein `NotAllowedError` zeigt an, dass Autofill nicht verfügbar ist oder die Seite den Fokus verloren hat, während ein `InvalidStateError` bedeutet, dass bereits ein Passkey im Provider existiert. Verwenden Sie vor dem Aufruf `getClientCapabilities()`, um die `conditionalCreate`-Unterstützung zu verifizieren, und prüfen Sie den Sichtbarkeitsstatus des Dokuments, um Ihre Fehlerzahlen nicht künstlich aufzublähen.

### Welchen Kontext sollte ich zusammen mit error.name protokollieren, damit WebAuthn-Fehler debuggbar werden?

Erfassen Sie den Operationstyp (Conditional UI, modaler Login, manuelles Create, Conditional Create oder Auto-Append), die Zeit bis zum Fehler seit Start der Operation, OS-Version, Browser-Version, Hardware-Modell, ob eine QR/Hybrid-UI erschien und eine Korrelations-ID, um eine Verbindung zu serverseitigen Logs herzustellen. Fehler bei der Server-Überprüfung wie eine abweichende Challenge, ungültige Signatur und nicht gefundene Credentials sollten als explizite, strukturierte Codes geloggt werden und nicht mit clientseitigen `DOMException`-Namen vermischt werden. Diese Signale zusammen ermöglichen die Einteilung der großen Mehrheit der Fehler in Kategorien, die ohne Raten behandelt werden können.
