---
url: 'https://www.corbado.com/id/blog/webauthn-errors'
title: 'Panduan Lengkap Kesalahan WebAuthn di Produksi (2026)'
description: 'Pelajari arti kesalahan WebAuthn umum seperti NotAllowedError dalam lingkungan produksi dan cara mengklasifikasikannya berdasarkan jenis operasi, pengaturan waktu, dan konteks platform.'
lang: 'id'
author: 'Vincent Delitz'
date: '2026-07-03T07:09:42.285Z'
lastModified: '2026-07-03T07:10:43.654Z'
keywords: 'kesalahan webauthn, NotAllowedError, AbortError, SecurityError, pemecahan masalah WebAuthn, klasifikasi kesalahan kunci sandi, ASAuthorizationError, Credential Manager, passkey, otentikasi'
category: 'WebAuthn Know-How'
---

# Panduan Lengkap Kesalahan WebAuthn di Produksi (2026)

## 1. Pengantar

Di lingkungan produksi, kesalahan WebAuthn membingungkan
karena browser mengekspos sekumpulan kecil nama `DOMException` (seperti `NotAllowedError`) yang
dapat mewakili berbagai penyebab yang mendasarinya. Selain itu, sebagian besar "kesalahan" -
sering kali di atas 95% dalam penerapan
kunci sandi skala besar yang dioptimalkan - sebenarnya merupakan
**perilaku yang diharapkan** (pengguna membatalkan prompt kunci sandi sistem operasi).

> Penting: Karena alasan privasi, browser tidak membedakan apakah pengguna aktif
> membatalkan atau tidak ada kunci sandi yang ada. Namun, dalam beberapa situasi dan dengan cukup
> konteks, baik di web maupun di platform native, beberapa kasus ini dapat
> dibedakan menggunakan sinyal seperti pengaturan waktu.

Jika Anda menginginkan definisi kanonis untuk nama-nama ini, mulailah dengan
[MDN `DOMException`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException). Untuk
kondisi spesifik WebAuthn yang mengarah ke pengecualian ini (dan yang wajib ditegakkan
oleh browser), lihat [spesifikasi Autentikasi Web W3C](https://www.w3.org/TR/webauthn-3/).

Jika Anda memperlakukan semua kesalahan sebagai "bug", Anda akan melakukan hal yang salah:

- Anda akan mencemari metrik kesalahan Anda dengan pembatalan normal
- Anda akan melewatkan regresi nyata yang tersembunyi di dalam banyaknya `NotAllowedError`
- Anda akan mengirimkan UI yang membingungkan pengguna alih-alih membantu mereka memulihkan diri

Dalam artikel ini kami menjawab:

- Apa arti nama kesalahan WebAuthn yang paling umum di lalu lintas nyata?
- Bagaimana Anda membedakan `NotAllowedError` ke dalam keranjang yang dapat ditindaklanjuti (batal vs waktu habis vs
  ketersediaan)?
- Mengapa kesalahan yang sama berarti hal yang berbeda bergantung pada operasi (login UI
  bersyarat vs login modal vs pembuatan kunci sandi vs
  pembuatan bersyarat)?
- Apa konteks minimum yang harus Anda tangkap sehingga "itu gagal" menjadi masalah yang dapat direproduksi?

## Key Facts

- `NotAllowedError` adalah **sinyal permukaan**, bukan akar penyebab. Ini bisa berarti pembatalan,
  waktu habis, "tidak ada kredensial lokal", atau tidak ada aktivasi pengguna tergantung pada konteks.
- **Tipe operasi mengubah maknanya.** `NotAllowedError` yang sama memiliki arti berbeda
  selama login UI bersyarat, login modal, pembuatan kunci sandi manual, pembuatan
  bersyarat dan penambahan yang dipicu otomatis.
- **Pengaturan waktu dari awal operasi** adalah sinyal yang paling diremehkan: segera (`<1 dtk`),
  pembatalan pengguna (1-15 dtk) dan waktu habis (30 dtk+) adalah kategori yang pada dasarnya berbeda.
- `AbortError` biasanya merupakan masalah siklus hidup/konkurensi (navigasi, render ulang, beberapa
  permintaan dalam proses).
- `SecurityError` hampir selalu konfigurasi/konteks dan langka dalam penerapan produksi yang matang.
- "Nama kesalahan browser" dan "penolakan verifikasi server" adalah lapisan yang berbeda. Lacak
  penolakan server sebagai kode eksplisit, bukan sebagai kegagalan klien generik.
- **Nama kesalahan mentah tidak dapat ditindaklanjuti secara langsung.** Selalu tangkap jenis operasi, pengaturan waktu dan
  konteks platform di samping `error.name` sehingga Anda dapat mengklasifikasikan kesalahan ke dalam keranjang yang
  benar-benar dapat Anda perbaiki.
- **"Lingkungan" lebih dari sekadar Browser + OS.** Untuk benar-benar memahami kesalahan, Anda harus
  melacak kombinasi penuh: Versi OS, Klien (Versi Browser/Aplikasi),
  Pengaturan Authenticator (misalnya, status iCloud/GPM) dan Model Perangkat Keras yang spesifik.
- **Kegagalan login adalah P1, kegagalan Pembuatan adalah P2.** Meskipun kesalahan pembuatan (P2) sering
  memiliki volume yang lebih tinggi karena pengguna meninggalkannya, kesalahan login (P1) memblokir akses dan memerlukan
  peringatan segera.

## 2. Lembar Panduan Produksi

Jika Anda hanya membutuhkan pemetaan cepat untuk membebaskan proses debug, mulailah dengan tabel ini. Ini berpihak
pada apa yang sebenarnya dilihat tim di dasbor dan tiket dukungan.

| **`error.name`**    | **Apa artinya biasanya di produksi**                                                                                              | **Apa yang harus diperiksa untuk konfirmasi**                                                                  | **Tindakan pertama (UX + teknis)**                                                                 |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `NotAllowedError`   | Lembar penolakan pengguna, batas waktu terlampaui, atau ketidaksesuaian ketersediaan yang dikumpulkan menjadi satu. Ini merupakan keranjang kesalahan terbesar di produksi. | waktu ke kesalahan, apakah UI QR/hybrid muncul, apakah upacara dimulai dari tindakan pengguna asli | Perlakukan sebagai hal yang wajar: pulihkan UI + tunjukkan opsi alternatif                                                  |
| `AbortError`        | Aplikasi Anda (atau browser) membatalkan upacara                                                                                   | navigasi/perenderan ulang selama upacara; panggilan WebAuthn serentak; `AbortController.abort()` | Batasi pada satu permintaan serentak; cegah perubahan rute; tangani pembatalan sebagai alur kontrol wajar                 |
| `SecurityError`     | Konteks/kebijakan tidak diizinkan                                                                                                  | asal + strategi ID RP; iframe/penyematan; HTTPS; kebijakan fitur                              | Perbaiki ID RP/konfigurasi asal; validasi kebijakan penyematan; pastikan konteks yang aman                 |
| `InvalidStateError` | Ketidaksesuaian status (sering kali karena pendaftaran ganda)                                                                                        | pendaftaran vs log masuk; `excludeCredentials`; ada kredensial yang sudah ada di pengautentikasi            | Anggap sebagai "sudah terdaftar"; sesuaikan rute UX; perbaiki pembuatan opsi                                |
| `ConstraintError`   | Persyaratan tidak dapat dipenuhi                                                                                                  | `authenticatorAttachment`, `userVerification`, persyaratan kunci residen                       | Longgarkan pembatasan atau berikan opsi lain/alternatif. Contoh: Pengunci layar tidak ada pada Android|
| `DataError`         | Input salah bentuk/tidak konsisten                                                                                                | pengodean base64url; format id/tantangan/penangan pengguna                                            | Perbaiki pengodean/serialisasi; tambahkan validasi pada pembuatan opsi                                    |
| `NotSupportedError` | Platform/browser tidak mendukung permintaan Anda                                                                                      | versi OS/browser; asumsi pendeteksian fitur                                              | Langsung gunakan alternatif; catat bagiannya; hindari menampilkan CTA passkey pada lingkungan yang tidak mendukung     |
| `UnknownError`      | Platform/pengautentikasi gagal secara umum                                                                                      | lonjakan setelah pembaruan OS; build perangkat; masalah dengan penyedia kredensial-manajer                     | UX yang dapat dicoba lagi; catat nomor build; cari tahu lebih lanjut mengenai lonjakan pada bagian tertentu                               |

Satu hal yang mudah terlewatkan: `error.name` yang sama bisa berarti hal yang sangat berbeda
bergantung pada **tipe operasi**. Tetap ingat konteks operasi saat Anda membaca
bagian di bawah ini. Praktiknya, kesalahan pembuatan kunci sandi
(pendaftaran) biasanya jauh melebihi jumlah kesalahan login - tabel di atas
berlaku untuk keduanya, tetapi pembuatan adalah tempat sebagian besar volume berada.

Selanjutnya, kita akan membahas lebih dalam `NotAllowedError` karena itu adalah salah satu yang paling sering Anda lihat dan
yang sering salah diartikan tim.

## 3. NotAllowedError: Operasi habis waktu atau tidak diizinkan

`NotAllowedError` sering terlihat seperti "kunci sandi gagal", tetapi biasanya itu adalah platform
yang memberi tahu Anda bahwa pengguna tidak menyelesaikan UI OS. Kuncinya adalah membaginya menjadi keranjang yang dapat Anda
tindaklanjuti.

**Apa yang akan Anda lihat di konsol browser:**

| **Sumber**     | **Pesan kesalahan**                                                                                                                                    |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 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.`                                                                                                                   |

Semua ini muncul sebagai `error.name === "NotAllowedError"`. `error.message` berbeda menurut
mesin browser dan penyebab yang mendasari, namun hasilnya sama: upacara tidak
selesai.

Ini berlaku untuk **login dan pembuatan kunci sandi**. Selama login (UI bersyarat, modal
dengan atau tanpa daftar yang diizinkan), `NotAllowedError` biasanya berarti pengguna tidak menyelesaikan
upacara. Selama pembuatan kunci sandi, kesalahan yang sama
muncul karena alasan yang berbeda: pengguna mengabaikan dialog pembuatan (pembuatan bersyarat
tidak berfungsi, atau halaman kehilangan fokus selama penambahan yang dipicu secara otomatis. Tipe operasi
mengubah makna kesalahan dan apa yang harus Anda lakukan tentangnya.

**Pengaturan waktu sering kali merupakan sinyal yang diremehkan.** Kegagalan setelah kurang dari satu detik klik adalah
biasanya penolakan langsung (lingkungan tidak bisa melakukannya, dokumen tidak difokuskan, kemampuan hilang).
Kesalahan setelah beberapa detik adalah pembatalan pengguna (mereka melihat dialog dan
memutuskan untuk tidak melanjutkan). Kesalahan setelah 30+ detik adalah batas waktu. Pada platform native,
pengaturan waktu sangat penting: perjalanan autentikator pulang pergi,
prompt biometrik dan penyerahan pengelola kredensial semuanya memiliki durasi karakteristik yang
membantu Anda memisahkan "tidak berfungsi" dari "pengguna pergi". Anda masih tidak dapat membedakannya
dengan mudah jika kunci sandi ada.

### 3.1 Disambiguate with Context

Anda tidak memerlukan sinyal yang sempurna. Anda memerlukan konteks yang cukup untuk menghindari memperlakukan setiap
`NotAllowedError` dengan cara yang sama. iOS/Safari mendapatkan
perhatian khusus di bawah ini karena ia memiliki kendala unik (persyaratan aktivasi pengguna
di versi sebelumnya), namun dalam volume kesalahan mentah, Windows dan Chromium browsers sering
menghasilkan lebih banyak `NotAllowedError` daripada platform lainnya. Sinyal-sinyal ini sering membuat Anda mendapatkan 80%
dari cara:

| **Sinyal**                                                   | **Kemungkinan arti**                                                                                                                                                                                                                                                                             | **Apa yang harus dilakukan selanjutnya**                                                                                                                                                                         |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Kegagalan langsung (`<1 dtk`)                                | Penolakan lingkungan: tidak ada kemampuan, dokumen tidak fokus, permukaan pembuatan bersyarat tidak tersedia                                                                                                                                                                                               | Periksa deteksi fitur; pastikan dokumen memiliki fokus; pastikan operasi didukung di platform ini                                                                                            |
| Pembatalan cepat (1-3 dtk)                                   | Perintah kejutan / tidak ada konteks                                                                                                                                                                                                                                                                    | Ubah waktu perintah; tambahkan waktu henti setelah pembatalan                                                                                                                                               |
| Pembatalan sepanjang pengguna (3-15 dtk)                     | Pengguna melihat dialog dan memilih untuk tidak melanjutkan                                                                                                                                                                                                                                                     | UX yang Diharapkan; pulihkan UI + tunjukkan fallback                                                                                                                                                       |
| Batas waktu (30 dtk+)                                        | Upacara habis waktu tanpa tindakan pengguna                                                                                                                                                                                                                                                           | Keranjang sebagai "tidak selesai"; pertimbangkan apakah perintah tersebut diperhatikan                                                                                                                         |
| UI QR/hybrid muncul sebelum kegagalan                        | Tidak ada kredensial lokal yang tersedia di perangkat ini. Catatan: secara andal mendeteksi keputusan kode QR sebelum hal tersebut terjadi memerlukan [intelijen kunci sandi](https://docs.corbado.com/corbado-connect/features/passkey-intelligence) yang mengetahui apakah terdapat kredensial yang dapat digunakan di perangkat saat ini. | Batasi penawaran kunci sandi; buat "Gunakan ponsel" eksplisit; kurangi kejutan QR                                                                                                                            |
| Terkonsentrasi di iOS/Safari dan terpicu tanpa klik/ketuk    | Aktivasi pengguna tidak ada                                                                                                                                                                                                                                                                         | Mulai upacara dari gerakan pengguna sungguhan                                                                                                                                                   |
| Saat pembuatan bersyarat atau tambahan yang terpicu otomatis | Isi otomatis tidak tersedia, kredensial sudah ada, atau halaman kehilangan fokus. Kesalahan pembuatan bersyarat dapat muncul tiba-tiba dan dalam volume tinggi ketika fitur diluncurkan, sehingga menjadikannya salah satu sumber kesalahan terbesar dalam semalam.                                                                    | Lihat pembuatan bersyarat; periksa status visibilitas dokumen; gunakan `getClientCapabilities()` untuk memverifikasi dukungan `conditionalCreate` sebelum mencoba panggilan tersebut |

Inilah juga mengapa `NotAllowedError` jarang terlihat oleh pengguna. Ini bukan pesan
yang dapat ditindaklanjuti oleh pengguna.

Klasifikasi konteks juga merupakan titik pembagian tingkat keberhasilan secara tajam. [Analisis tingkat keberhasilan autentikasi kunci sandi Tolok Ukur Kunci Sandi Corbado 2026](https://www.corbado.com/passkey-benchmark-2026/passkey-authentication-success-rate)
mengukur penyelesaian Q1 2026 sebesar 55–95% untuk alur pengidentifikasi-pertama perangkat yang tidak dikenal versus
95–99% untuk pengembalian perangkat yang dikenal di seluruh
penerapan B2C skala besar.
Pengidentifikasi-pertama web iOS mendarat di penyelesaian 85–95%
(% CDA 0–5%), web Android pada 70–85% (% CDA 5–10%) dan web macOS pada 70–85% (% CDA 10–15%),
sementara web Windows duduk di 45–60% penyelesaian pengidentifikasi-pertama dengan % CDA di 55–65% pada
Windows 11 dan 40–55% pada Windows 10. Membaca
volume `NotAllowedError` tanpa memisahkan konteks perangkat yang dikenal versus perangkat yang tidak dikenal menggabungkan
dua rezim keberhasilan yang secara mendasar berbeda.

Satu nuansa yang penting dalam produksi: beberapa user agent dapat memunculkan batas waktu sebagai
`TimeoutError`, namun banyak tim masih melihat batas waktu mengerucut menjadi `NotAllowedError` di
dasbor. Bagaimanapun, perlakukan batas waktu sebagai “upacara tidak selesai” dan kelompokkan menggunakan
waktu beserta konteks.

### 3.2 Penanganan UX: buat Pembatalan menjadi Keluar normal

Ketika lembar OS diabaikan atau habis waktunya, UI Anda harus segera pulih dan
bereaksi dengan baik. Serangkaian aturan praktis:

- kembalikan UI masuk (jangan ada pemutar yang terus berjalan)
- pertahankan status pengenal (jangan memaksa masuk kembali)
- tampilkan alternatif yang terlihat di layar yang sama
- hindari spanduk menakutkan untuk hasil yang diharapkan

Di luar hal dasar:

- Perlakukan pembatalan pertama sebagai hal biasa dan tawarkan opsi coba lagi dengan penjelasan yang tenang. Hanya setelah pembatalan
  kedua Anda harus menyarankan opsi alternatif (lihat
  cadangan dan pemulihan kunci sandi).
- Izinkan maksimal tiga prompt pembuatan sebelum jeda waktu agar pengguna yang terkejut mendapat kesempatan
  kedua (lihat praktik terbaik pembuatan kunci sandi).
- Pisahkan jumlah kesalahan antara pembuatan dan masuk agar Anda membandingkan apel dengan apel.
- Kelompokkan tingkat kesalahan berdasarkan OS, browser, dan perangkat agar Anda dapat melihat di mana sebenarnya hambatan
  terjadi (lihat praktik terbaik masuk kunci sandi).

Jika "pembatalan" Anda benar-benar tinggi, langkah selanjutnya adalah memperbaiki akar masalah di baliknya:
waktu perintah, kejutan QR, dan ketersediaan yang rendah.

### 3.3 Perbaikan Teknik yang mengurangi NotAllowedError

Mulai dengan perubahan yang memindahkan metrik dengan cepat:

- Perbaiki pengaturan waktu perintah dan aktivasi pengguna (terutama pada
  iOS/Safari): Kejadian yang diaktifkan pengguna WebAuthn Safari.
- Kurangi kejutan QR/hybrid: mengapa alur passkey menunjukkan kode QR dan pengguna meninggalkannya.
- Batasi tawaran agar passkey ditampilkan saat kemungkinan besar berhasil: tawarkan passkey hanya bila kemungkinan besar akan berhasil.
- Gunakan pola yang menghindari permintaan saat tidak ada kredensial lokal:
  Mediasi segera WebAuthn.
- **Tangani Ketidakstabilan Jaringan:** Kesalahan jaringan selama verifikasi sering kali terwujud sebagai
  kegagalan klien yang generik. Terapkan antrean offline untuk pencatatan telemetri Anda sehingga
  Anda tidak kehilangan data kesalahan saat koneksi pengguna terputus selama upacara berlangsung.
- **Batasi upacara dengan API deteksi** sehingga kegagalan lingkungan tidak menggelembungkan
  keranjang `NotAllowedError` Anda. Mulai dengan
  `isUVPAA()` sebagai 
  pembatas paling dasar, lalu gunakan `getClientCapabilities()` untuk
  pemeriksaan yang lebih baik (pembuatan bersyarat, penerimaan bersyarat, transportasi hybrid,
  pengautentikasi platform). Perhatikan bahwa 
  API deteksi dapat rusak pada pembaruan OS: iOS 26.2 meluncurkan bug WebKit
  di mana `isUVPAA()` menghasilkan `false` pada semua browser berbasis WKWebView
  meskipun passkey berfungsi dengan baik, menyebabkan lonjakan `NotAllowedError` mendadak bagi
  10-25% pengguna iOS (lihat memperbaiki deteksi passkey dengan
  getClientCapabilities()).

### 3.4 Catatan mengenai Nama Kesalahan yang berkembang

Nama-nama kesalahan adalah target yang bergerak. Ada berbagai proposal berkelanjutan untuk menambah rincian kesalahan WebAuthn
(misalnya, untuk memisahkan “tidak ada kredensial yang tersedia” dari “pengguna yang membatalkan”). Sejak
Februari 2026, hal tersebut belum diterapkan di dalam sebagian besar peramban, jadi ada baiknya membangun keranjang
alasan Anda sendiri berdasarkan konteks dan waktu. Bila Anda ingin melacak pekerjaan ini, lihat
[WebAuthn issue #2062](https://github.com/w3c/webauthn/issues/2062) dan
[penjelas "Kode Kesalahan Baru"](https://github.com/w3c/webauthn/wiki/Explainer%3A-New-Error-Codes-%282024-Edition%29).

Nama-nama kesalahan lainnya kurang sering terjadi namun tetap berguna untuk dipahami bila
muncul.

## 4. AbortError: Operasi dibatalkan

`AbortError` tidak umum dalam volume jika dibandingkan dengan `NotAllowedError`, tetapi saat muncul ini
sangat diagnostik: ini biasanya berarti upacara tidak selesai karena aplikasi Anda
membatalkan permintaan - navigasi terjadi, state berubah, atau permintaan kedua dimulai.

**Apa yang akan Anda lihat di konsol browser:**

| **Sumber**     | **Pesan kesalahan**                                       |
| -------------- | --------------------------------------------------------- |
| 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.` |

Penyebab umum produksi meliputi:

- beberapa panggilan WebAuthn serentak (dua prompt balapan)
- perubahan rute/perenderan ulang saat upacara yang sedang berlangsung
- memanggil `AbortController.abort()` selama pencobaan ulang atau pembersihan status

Untuk memperbaikinya, berfokuslah untuk menjadikan upacara sebagai "bagian kritis":

- hanya bolehkan satu permintaan dalam proses secara bersamaan
- blokir navigasi selama upacara (atau batalkan secara bersih dan pulihkan UI)
- perlakukan pembatalan sebagai aliran kendali yang diharapkan: tampilkan tombol coba lagi dan metode alternatif

Jika Anda melihat `AbortError` terkonsentrasi di permukaan yang disematkan atau aplikasi multimesin, hal berikutnya
yang harus diperiksa adalah `SecurityError`.

## 5. SecurityError: WebAuthn tidak didukung pada situs dengan kesalahan sertifikat TLS

`SecurityError` adalah browser yang memberitahu Anda: "konteks ini tidak diizinkan untuk melakukan yang
Anda minta." Dalam praktik, hampir selalu soal konfigurasi, bukan perilaku pengguna. Pada pengerahan
produksi yang sudah matang, `SecurityError` langka terjadi karena masalah ini umumnya sudah tertangkap
saat tes integrasi. Jika ini muncul di produksi, umumnya hal ini berarti ada penambahan
domain baru, penyematan konteks, atau sasaran pengerahan yang dilakukan tanpa konfigurasi WebAuthn
yang tepat.

Penyebab-penyebab umum termasuk:

- RP ID / kegagalan kecocokan muasal (setelan multi-domain)
- larangan penyematan asalan-bersilang (iframe)
- konteks tidak aman (bukan HTTPS) atau terblokirnya hak/kebijakan
- `.well-known/webauthn` atau `.well-known/assetlinks.json` salah konfigurasi, hilang, atau
  tidak tersedia sementara. Isu jaringan saat terjadi kondisi krusial yang saat mana browser
  mengambil berkas-berkas ini bakal menimbulkan kegagalan. Satu rupa buta yang umum: jika halamamuka Anda turun
  untuk di-maintenance, berkas-berkas well-known juga ikutan offline, lantas merusak perayaan kunci sandi
  lintas seluruh pihak-tergantung yang memerlukannya.

**Apa yang bakal Anda lihat dalam konsol browser:**

| **Sumber**      | **Pesan galat**                                                                                                                  |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Chrome, Edge    | `SecurityError: WebAuthn is not supported on sites with TLS certificate errors.`                                                 |
| Any 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.`                                     |

Dalam produksi, `SecurityError` langka terjadi - ini lumrah tertangkap saat tes integrasi.
Ketika ini terjadi, kesalahan sertifikat TLS yang paling umum bertahan hidup.

Loop debugging paling cepat adalah:

- masuk pada asal dan RP ID masukan yang Anda gunakan
- perbanyak dalam konteks sama (top-level vs iframe,
  prod domain vs staging)
- jika Anda menyematkan log-masuk, tetapkan kebijakan izin sudah di-setel (misalnya
  `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)
- pastikan taktik domain Anda (lihat
  asal berkaitan)
- jika Anda memakai iframe, validasi kebijakan fiturnya (lihat
  kunci sandi iframe)

Setelah `SecurityError` di-urus, wadah selanjutnya yang patut ditangani secara serius adalah rangkaian kesalahan
yang menandakan bug penerapan: `InvalidStateError`, `ConstraintError` serta
`DataError`.

## 6. InvalidStateError, ConstraintError, DataError: perlakukan sebagai Bug Implementasi

Kesalahan-kesalahan ini harus langka dalam implementasi kunci sandi yang matang. Jika muncul, mereka
biasanya menunjukkan bahwa opsi generasi salah untuk suatu segmen atau aliran ada dalam keadaan
salah.

### 6.1 InvalidStateError: "kredensial sudah terdaftar pada relying party"

**Apa yang akan Anda lihat di konsol browser:**

| **Sumber**     | **Pesan kesalahan**                                                                                                                                  |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| 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`                                                       |

Arti tipikal:

- pendaftaran: Anda mencoba untuk membuat kredensial yang sudah ada (duplikat)
- log masuk: kurang umum; seringkali berarti alur/keadaan inkonsisten untuk platform tersebut

Penanganan praktis:

- jika terjadi pada registrasi manual, perlakukan sebagai "sudah terdaftar" dan rutekan
  secara tepat
- pastikan `excludeCredentials` mencantumkan seluruh ID kredensial eksisten untuk pengguna sehingga
  autentikator dapat mendeteksi duplikat (lihat
  excludeCredentials)
- selama pembuatan kondisional, `InvalidStateError` merupakan
  harapan dan sebaiknya diabaikan dalam diam: artinya sebuah kunci sandi sudah eksis dalam
  provider. Hal yang sama juga berlaku untuk `NotAllowedError` dan `AbortError` selama
  pembuatan kondisional (lihat
  [conditional create on Chrome](https://developer.chrome.com/docs/identity/webauthn-conditional-create))

### 6.2 ConstraintError

Arti Umum: authenticator tidak dapat memenuhi
kendala yang Anda minta.

Pemicu umum:

- penguncian layar perangkat hilang (terutama Android):
  platform membutuhkan verifikasi biometrik atau PIN, tetapi perangkat tersebut tidak mempunyai layar kunci yang dikonfigurasi
- `authenticatorAttachment` terlalu ketat atau
  kunci residen
  asumsi
- kendala `userVerification` pada segmen-segmen di mana hal tersebut tidak tersedia

Memperbaiki: ringankan kendala (jika dimungkinkan) atau tawarkan rute alternatif. Untuk layar kunci yang hilang, 
pertimbangkan pendeteksian kondisi ini lalu arahkan user ketimbang membiarkan kegagalan berlalu tanpa notifikasi (Android).

### 6.3 DataError

Arti khas: masukan tidak berbentuk dengan baik atau inkonsisten.

Pemicu yang lazim:

- kesalahan pada saat penyandian (base64 vs base64url)
- id kredensial yang cacat / tantangan pada pemformatan

Solusi: validasi dan normalisasi masukan di perbatasan tempat Anda mengonfigurasi WebAuthn opsional. Dalam
penerapannya, `DataError` secara praktis ditiadakan di dalam platform sistem pengerjaan—seandainya pembuatan pilihan Anda
telah diuji, Anda takkan melihatnya di panel informasi Anda.

Kala semua kesalahan ini ditangani, kendala berikutnya adalah tentang jangkauan: apakah user tak dapat menaut
karena gawai yang dipakai tidak sesuai dengan dukungan WebAuthn yang Anda rancang?

## 7. NotSupportedError: Agen pengguna tidak mendukung kredensial kunci publik

`NotSupportedError` adalah sinyal cakupan, bukan sinyal keandalan. Biasanya ini berarti suatu
segmen tidak dapat melakukan apa yang Anda minta (versi OS/browser terlalu lama, kemampuan tidak ada, fitur tidak
diaktifkan).

**Apa yang akan Anda lihat di konsol browser:**

| **Sumber**            | **Pesan kesalahan**                                                                              |
| --------------------- | ---------------------------------------------------------------------------------------------- |
| 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`      |

Dua hal pertama adalah DOMException `NotSupportedError` asli. Entri `TypeError` 
secara teknis adalah tipe pengecualian yang berbeda tetapi mewakili kelas masalah yang sama:
browser atau lingkungan tidak mendukung apa yang Anda minta. Rumpun `TypeError` serialisasi
JSON jauh lebih umum dalam praktiknya daripada DOMException `NotSupportedError`
itu sendiri (lihat di bawah).

Penyebab umum meliputi:

- versi browser/OS lama yang tidak mendukung dasar WebAuthn
- meminta fitur WebAuthn yang tidak tersedia di platform tersebut
- mencoba alur platform-spesifik di perangkat yang tidak didukung

**Rumpun serialisasi JSON adalah sumber terbesar dari kegagalan kelas `NotSupportedError`
di produksi.** Secara teknis ini muncul sebagai `TypeError` (metode hilang), bukan
sebagai `DOMException`, tetapi di sinilah Anda akan menemukannya. Dua penyebab dasar berbeda:

1. **Browser tidak mendukung metode serialisasi JSON WebAuthn.** Browser memiliki
   `navigator.credentials` tetapi bukan `PublicKeyCredential.parseCreationOptionsFromJSON` /
   `parseRequestOptionsFromJSON`. Ini merupakan sekitar 90% dari rumpun kesalahan ini,
   terkonsentrasi pada versi Safari dan Chrome lama. Jika perpustakaan klien Anda bergantung pada
   metode ini tanpa cadangan, ini menghasilkan volume kesalahan yang signifikan.
2. **Ekstensi pengelola kata sandi merusak `.toJSON()`.** Ekstensi seperti
   Bitwarden,
   LastPass, atau
   1Password dapat mencegat
   upacara dan mengembalikan objek yang terlihat seperti kredensial tetapi bukan
   instance `PublicKeyCredential` yang sebenarnya. Memanggil `.toJSON()` padanya akan gagal, mengembalikan
   tidak terdefinisi, atau objek tersebut `null` seluruhnya. Ini adalah sekitar 10% dari rumpun tetapi
   terutama membingungkan untuk debug karena pesan kesalahan berbeda menurut browser (Safari:
   "Can only call on instances of PublicKeyCredential"; Firefox: "does not implement
   interface PublicKeyCredential").

Penanganan harus tegas dan cepat:

- segera kembali ke kata sandi/OTP cadangan
- catat segmen sehingga Anda dapat mengukur kesenjangan cakupan
- hindari menampilkan CTA passkey pada segmen yang akan selalu gagal

Jika cakupan terlihat baik tetapi kegagalan masih terjadi pada segmen tertentu, Anda mungkin menghadapi
masalah lapisan platform yang muncul sebagai `UnknownError`.

## 8. UnknownError: Terjadi kesalahan yang tidak diketahui saat berbicara dengan pengelola kredensial

`UnknownError` adalah serba-bisa untuk kegagalan autentikator/OS yang tidak dipetakan secara jelas ke dalam
kategori lain. Ini sering kali sementara, tetapi juga dapat melonjak setelah pembaruan OS.

**Apa yang akan Anda lihat di konsol browser:**

| **Sumber**         | **Pesan kesalahan**                                                                                                                     |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| Chrome (Android)   | `UnknownError: An unknown error occurred while talking to the credential manager.`                                                      |
| Browser apa saja   | `UnknownError: The operation failed for an unknown transient reason.`                                                                   |
| Browser apa saja   | `UnknownError: Either the device has received unexpected request data, or the device has been reconfigured since the request was made.` |
| Browser apa saja   | `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`                                                                                                                     |

Penanganan praktis:

- gunakan UX yang ramah untuk mencoba lagi (jangan "menyalahkan pengguna")
- ambil OS/nomor build dan konteks credential-manager/provider di mana dimungkinkan
- waspadai lonjakan spesifik segmen setelah pembaruan OS

Satu sumber kesalahan yang unik dan tidak masuk secara rapi ke dalam kategori `DOMException` mana pun:
**ekstensi browser manajer kata sandi** (seperti
Bitwarden,
LastPass,
1Password, dan lain-lain) dapat mencegat
panggilan API WebAuthn dan mengembalikan tanggapan non-standar. Meskipun kecil dalam volume dibandingkan dengan
pembatalan pengguna, kesalahan ini berharga untuk dilacak karena mereka memengaruhi segmen pengguna tertentu
secara konsisten dan gejala-gejalanya membingungkan: metode yang hilang dari objek kredensial yang dikembalikan,
tipe kesalahan yang tidak terduga, atau tanggapan cacat yang tidak cocok dengan satupun
kesalahan WebAuthn yang terdokumentasi. Kesalahan-kesalahan ini sering kali timbul sebagai `UnknownError` atau sebagai
pengecualian yang tidak terklasifikasi. Jika
Anda melihat adanya lonjakan kesalahan yang terkonsentrasi di dalam peramban tertentu tanpa alasan dari OS itu sendiri, periksa
apakah suatu ekstensi manajer kredensial terkait.

Selama ini kami hanya meliputi penamaan kesalahan penjelajah peramban saja. Tetapi jika Anda juga mengekspor aplikasi lokal, maka
pemandangan kesalahan pun turut menjadi lain - serta dalam sedikit hal, lebih berarti.

## 9. Sepatah Kata mengenai Aplikasi native (iOS dan Android)

Segala hal di atas mencakup peramban web. Aplikasi native - iOS dengan rangka ASAuthorization, Android beserta Manajer Kredensial -
membagikan rumpun kesalahan sama pada kategori dasar mereka melainkan agak sedikit berbeda dalam arti yang lebih luas:

1. **"Tidak ada kredensial" adalah sinyal yang berbeda.** Di web, peramban menyatukan "tidak ada kredensial
   yang tersedia" dan "pengguna membatalkan" ke dalam `NotAllowedError` yang sama demi privasi. Di ranah native,
   menggunakan `preferImmediatelyAvailableCredentials` di iOS (`ASAuthorizationController`) atau
   `setPreferImmediatelyAvailableCredentials(true)` di
   Android (`GetCredentialRequest`) akan memberitahukan OS
   hanya untuk menyajikan kredensial yang sudah ada di perangkat dan langsung gagal jika tidak ada kredensial tersebut.
   Ini memberi Anda kembalian "tanpa kredensial" yang bersih, sesuatu yang tidak dapat diberikan oleh web.

2. **Status penyedia kredensial tampak.** Platform native dalam beberapa kondisi dapat
   memberitahu Anda jika tidak ada penyedia kredensial (Google Password Manager,
   iCloud Keychain,
   1Password, dll.) yang dipasang,
   dikonfigurasi, atau disetel sebagai nilai default lalu bereaksi terhadapnya. Pada web,
   informasi ini tersembunyi di balik pesan buram `NotAllowedError`.

3. **Pesan kesalahan lebih spesifik.** Oleh karena sang pengguna telah memasang aplikasi tersebut - dan
   dengannya membuat satu hubungan kepecayaan dengan
   pihak terkait - maka OS memberi rincian diagnosisnya.
   Pertimbangan keprivasian yang secara paksa menekan peramban di web agar menyamarkan kesalahannya
   tidak berlaku sejalan kala pengaplikasian tersebut nyata sudah berada di gawai. iOS menyuguhkan pesan terlokalisasi di
   dalam gawai berdasarkan preferensi bahasa penggunanya. Android mengantarkan sejenis penataan
   struktur kesalahan lewat urutan permasalahannya. Karenanya perbaikan jauh lebih ringkas walaupun arti pada hal itu menuntun penanganan
   yang mengharuskan agar penyetelan dapat melokalisasi bentuk format kesalahan khas-platform.

### 9.1 iOS (Kerangka ASAuthorization)

iOS memunculkan kesalahan kunci sandi melalui kerangka ASAuthorization. Semua kesalahan tiba dalam
callback delegasi `authorizationController(controller:didCompleteWithError:)` sebagai
objek `NSError`.

**Klasifikasikan berdasarkan domain + kode, bukan berdasarkan string pesan.** Domain kesalahan utama adalah
`com.apple.AuthenticationServices.AuthorizationError`
(`ASAuthorizationError.errorDomain`). Cast kesalahan dengan `let nsError = error as NSError`
dan cocokkan pada `.domain` dan `.code`. Jangan pernah mencocokkan pada `.localizedDescription` di produksi -
pesan-pesan Apple dilokalkan ke 30+ bahasa dan dapat berubah seiring versi OS. String
pesan yang terdaftar di bawah ini berguna untuk mengenali kesalahan dalam catatan (log), tetapi itu bukanlah
kriteria klasifikasi.

**Kode ASAuthorizationError Publik:**

| **Kode** | **Nama**                                | **Sejak** | **Apa artinya**                                                                                                                                                                                                                                                                                                      |
| -------- | --------------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1000     | `Unknown`                               | iOS 13    | Tidak boleh muncul dalam produksi. Hal umum untuk menangkap-semua.                                                                                                                                                                                                                                                                 |
| 1001     | `Canceled`                              | iOS 13    | Pengguna menepis lembaran passkey. Kesalahan terumum yang ada - setara `NotAllowedError`. Tanda bersih dengan `userInfo` kosong dan tiada kesalahan mendasar.                                                                                                                                                          |
| 1002     | `InvalidResponse`                       | iOS 13    | Kerusakan tingkatan kerangka kerja. Langka dalam pengerjaannya.                                                                                                                                                                                                                                                      |
| 1003     | `NotHandled`                            | iOS 13    | Tak ada provider yang menangani permintaan. Periksa setelan hak-guna serta provider.                                                                                                                                                                                                                                |
| 1004     | `Failed`                                | iOS 13    | Gagal pada umumnya. Terdapat keterangan nyata pada `localizedDescription` (semisal "Aplikasi beserta tanda kenal X tak bersangkut paut dengan ranah Y"). `userInfo` bisa menampung tulisan `FailureReason`, hanya saja tak selamanya `NSUnderlyingErrorKey` diisi - kegagalan penyatuan domain nihil nilainya bagi yang tersembunyi. |
| 1005     | `NotInteractive`                        | iOS 15    | Kredensial tidak sedia apabila menggunakan opsi preferImmediatelyAvailableCredentials`. Hal begini tanda bersih "tak dijumpai" - kesetaraan iOS dari perihal "tiada passkey pada perangkat." Antar muka sama sekali tak dimunculkan.                                                                                        |
| 1006     | `MatchedExcludedCredential`             | iOS 18    | Passkey bagi RP peranti tersebut telah tersedia di dalamnya. Tanda jernih melacak gandaan - `userInfo` hampa, tanpa `NSUnderlyingErrorKey`. Tata urut berlaku walau tanpa menilik huruf.                                                                                                                                |
| 1007     | `CredentialImport`                      | iOS 18.2  | Impor kredensial tak berhasil.                                                                                                                                                                                                                                                                                       |
| 1008     | `CredentialExport`                      | iOS 18.2  | Ekspor kredensial tak berhasil.                                                                                                                                                                                                                                                                                      |
| 1009     | `PreferSignInWithApple`                 | iOS 26    | Pemakai cenderung Memasuki sistem menggunakan layanan masuk dengan ID Apple alih-alih kunci aksesnya. Baru dalam rilis iOS kali ini.                                                                                                                                                                                |
| 1010     | `DeviceNotConfiguredForPasskeyCreation` | iOS 26    | Piranti kurang kata-sandi pembuka-layar maupun Keychain di lingkungan iCloud-nya. Inilah kelemahan simulator pada peluncuran OS kali ini: menampilkan ralat yang semestinya tak ada kendati kesemuanya beraturan dan beres (terbebas terhadap perangkat aslinya).                                                    |

Perbedaan terpenting pada lingkungan produksi: **sejak dirilisnya sistem operasi teranyar itu, jejak duplikasi
mengirimkan notifikasi galatnya pribadi berkode 1006 (`MatchedExcludedCredential`).** Dalam
penggunaan terdahulu di edisi sebelumnya, sisa duplikat terbungkus
jauh di bawah notifikasi `Failed` (1004). Kini
pada platform teranyar ini perbedaannya tersusun
(kode yang beda) alih-alih cuma rentetan kalimat.

**Masalah umum di masa berjalannya sistem operasi (batas perinci-baca):**

Uraian-uraian ini menyingkap di `localizedDescription` serta `userInfo` buat kekhususan aneka-salah
. Memanfaatkan hal tersebut berguna di penapisan maupun pengusutan dan penelusuran, walau tidak sepadan untuk pembagian berjenjang pada rancang kodenya.

| **Pesan (Lokal Bahasa Inggris)**                                              | **Kode dasar**     | **Catatan**                                                                                                                                    |
| ------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `Application with identifier <TeamID.BundleID> is not associated with domain X` | 1004 (`Failed`)     | Entitlement Associated Domains aplikasi tidak cocok dengan relying party. Perbaiki file `apple-app-site-association` di server Anda.          |
| `Couldn't communicate with a helper application.`                               | 1004 (`Failed`)     | Ekstensi penyedia kredensial gagal merespons. Sementara - percobaan ulang sudah tepat.                                                          |
| `Request already in progress for specified application identifier.`             | 1004 (`Failed`)     | Permintaan ASAuthorization duplikat terkirim saat ada permintaan yang tertunda. Race condition di aplikasi.                                     |
| `Stolen Device Protection is enabled and biometry is required.`                 | 1004 (`Failed`)     | Perlindungan Perangkat yang Dicuri di iOS 17+ memblokir autentikasi biometrik di lokasi asing. Tidak dapat ditindaklanjuti oleh pengembang, tetapi layak ditampilkan kepada pengguna. |
| `(AuthenticationServicesCore.ASCABLEClient.ClientError error 2.)`               | Domain terpisah     | Jabat tangan Bluetooth autentikasi lintas perangkat (hybrid/CABLE) gagal.                                                                      |
| `(AuthenticationServicesCore.ASCABLEClient.ClientError error 3.)`               | Domain terpisah     | Koneksi Bluetooth autentikasi lintas perangkat gagal.                                                                                          |

**Pesan "tidak ada kredensial" lokal (kode 1005):**

Bila `preferImmediatelyAvailableCredentials` ditetapkan dan tak terdapat sandi, iOS memberi kembalian
galat berkode 1005 (`NotInteractive`) berwujud kabar terlokalkan ke dalam bahasa asli sang pengguna yang tersetel pada gawai
kepunyaannya. Cuma ini yang dapat ditemui bagi perangkat tersemat secara bawan—mesin penjelajah pun urung
memunculkannya sekelumit juga. Keterangan tersebut senantiasa diawali kalimat `The operation couldn't be completed.`
(Bahasa Inggris) beriring teks tertata berdasarkan lokalisasinya di antaranya:

| **Bahasa**            | **Pesan**                                                                            |
| --------------------- | ------------------------------------------------------------------------------------ |
| Mandarin (Sederhana)  | `没有可用于登录的凭证。`                                                             |
| Vietnam               | `Không có sẵn thông tin để đăng nhập.`                                               |
| Arab                  | `لا تتوفر بيانات اعتماد لتسجيل الدخول.`                                              |
| Spanyol               | `No hay ninguna credencial disponible para iniciar sesión.`                          |
| Mandarin (Tradisional)| `沒有可用於登入的憑證。`                                                             |
| Korea                 | `로그인을 위한 자격 증명이 없습니다.`                                                |
| Prancis (Kanada)      | `Aucun identifiant disponible pour la connexion.`                                    |
| Portugis (Brasil)     | `Nenhuma credencial disponível para login.`                                          |
| Prancis (Prancis)     | `Aucune information d'identification n'est disponible pour procéder à la connexion.` |
| Thai                  | `ไม่มีข้อมูลประจำตัวสำหรับเข้าสู่ระบบ`                                               |
| Italia                | `Non ci sono credenziali disponibili per l'accesso.`                                 |
| Belanda               | `Geen inloggegevens beschikbaar.`                                                    |
| Jepang                | `ログイン用の資格情報がありません。`                                                 |
| Turki                 | `Oturum açmak için kullanılabilecek kimlik bilgisi yok.`                             |

Perangkat dengan lokal bahasa Inggris biasanya menyelesaikan "tidak ada kredensial" di level API sebelum kerangka kerja
ASAuthorization mengembalikan kesalahan yang dilokalkan, itulah sebabnya tidak ada varian bahasa Inggris yang
muncul di atas. Secara programatik, selalu cocokkan pada kode 1005 daripada mengurai string
ini.

### 9.2 Android (Credential Manager API)

Android memunculkan kesalahan kunci sandi melalui Credential Manager API
(`androidx.credentials`). Pesan kesalahan mencakup pesan utama dan sering kali sebuah `cause`
dengan rincian tambahan. Dibandingkan dengan iOS, Android memberikan tipe kesalahan yang lebih terstruktur dan
penyebab yang lebih jelas untuk masalah konfigurasi.

**Pembatalan pengguna dan deteksi kredensial:**

| **Kesalahan**                                       | **Catatan**                                                                                                                                                                                               |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `User cancelled the operation`                    | Pengguna membatalkan prompt passkey. Setara dengan `NotAllowedError`. Catatan: Credential Manager juga mengembalikan `User canceled the request` (ejaan AS) dari path kode yang berbeda - keduanya sama. |
| `Excluded credential matches existing credential` | Passkey sudah ada untuk ID kredensial ini. Setara dengan `InvalidStateError`. Berbeda dengan iOS, pesannya terpisah dari pembatalan pengguna.                                                          |
| `No create options available.`                    | Tidak ada penyedia kredensial yang memenuhi syarat yang dapat menangani permintaan pembuatan. Biasanya berarti Google Play Services sudah usang atau tidak ada penyedia kredensial yang mendukung pembuatan passkey.   |

**Kesalahan konfigurasi dan keamanan:**

| **Kesalahan**                                                                  | **Catatan**                                                                                                                                       |
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Passkeys not supported for this app`                                          | Digital Asset Links (`assetlinks.json`) tidak ada atau tidak memuat sidik jari sertifikat penandatanganan aplikasi. Setara dengan `SecurityError`. |
| `Https failed: respCode=301, url=https://<domain>/.well-known/assetlinks.json` | Berkas `assetlinks.json` mengembalikan redirect, bukan HTTP 200. Android mensyaratkan berkas ada di URL pasti tanpa pengalihan.                  |
| `The incoming request cannot be validated`                                     | Credential Manager tidak dapat memverifikasi permintaan terhadap Digital Asset Links.                                                                     |
| `RP ID cannot be validated.`                                                   | Identitas relying party pada opsi WebAuthn tidak sesuai dengan isi `assetlinks.json`.                                                                    |
| `Screen lock is missing.`                                                      | Tidak ada PIN, pola penguncian maupun autentikasi biometrik pada setelan gawainya. Kunci-sandi butuh verifikasi pengguna. Setara perlakuan terhadap kendala galat atau constraint-nya.                   |
| `Cannot find an eligible account.`                                             | Tak sepotong nama pun dari sekian kumpulan pendaftaran atas dasar sistem buatan mbah "Google" itu memenuhi ketentuan persyaratan dalam hal mencetak maupun mengkaryakan anak kunci. Hal amat ganjil seperti langkanya pengerahan instalasi khusus kelas bisnis besar (custom).|

**Kesalahan platform dan autentikator:**

| **Kesalahan**                                                                            | **Catatan**                                                                                                                                                                                                                                        |
| ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Unsuccessful result from folsom activity.`                                              | Kegagalan internal Google Play Services. "Folsom" adalah komponen GMS untuk operasi passkey. Bersifat sementara - coba lagi wajar dilakukan.                                                                                                                       |
| `Can't find the proper key to decrypt the private key from WebauthnCredentialSpecifics.` | Kunci sandi yang disinkronkan sudah ada tetapi peranti urung mendeskripsikan kunci asalnya di pihak internal Google Manager dengan keadaannya yang kacau. Sandinya sendiri diimpor bersilang kendati dekripsi-kuncinya tiada dapat diraih. |
| `Operation was interrupted` (cause: `The UI was interrupted - please try again.`)        | Antarmuka Pengelola Kredensial (Credential Manager) mendadak diselang/tumpang-tindihkan sama giat lain semisal seruan panggilan darurat atau penataan balik/pergantian hadap layar. Serupalah hal itu dengan peristiwa Abort Error (terhenti paksa).                                                                 |
| `Unknown credential error`                                                               | Sifat lazim jika urung diselidiki di rupa mana dan pada letak apanya si kutu keparat bermukim maupun bercokol pada sekuritas sang pengguna yang tidak mengatasnamakan bagian yang mana pun pada ralat. Semisal ralat pada penampungan sementara atau kilasan waktu.                                 |
| `timeout` (cause: `Canceled`)                                                            | Upacara otentikasi di pengatur kredensial menampakkan sisa waktunya sebelum sang pelanggan menyelesaikan serangkaian langkah proses pengecekan berbasis keunikan pada biometrik maupun pengenal muka pada kamera selular pintar miliknya. |

## 10. Menyusun semuanya bersama: Taksonomi Kesalahan

Diagram berikut ini memperlihatkan bagaimana sekalian tata urutan mulai tingkat Papan Prasarana (Sistem Utama)
berujung deteksi hingga tingkatan Operasional terhubung utuh berjenjang atas bawah pada bagannya masing-masing. Gambar bagan di bawah patutnya dibikin
konsep tata rancangnya kala berupaya dalam perekaman atas tiap-tiap notifikasi kesalahan yang mengemuka saat terjadinya.

```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/Jaringan)"]
        direction TB
        ServerErr["Kesalahan Sisi Server<br/>500 / Kesalahan Logika"]:::network
        NetErr["Kesalahan Jaringan<br/>Batas Waktu / 400 Bad Request"]:::network

        ServerErr & NetErr -->|Terwujud sebagai| ClientManifest["Kesalahan Generik Sisi Klien"]
    end

    %% --- CENTER: THE ENVIRONMENT STACK (From Sketch) ---
    subgraph Environment ["Lingkungan (Sisi Klien)"]
        direction TB

        %% Layer 1: Platform Type
        subgraph Type ["Lapisan 1: Platform"]
            Web["Web / Browser"]
            Native["Native / Aplikasi"]
        end

        %% Layer 2: OS Context
        subgraph OS_Layer ["Lapisan 2: OS & Versi"]
            OS_Web["OS: Windows, macOS, Linux"]
            OS_Nat["OS: iOS, Android"]
            OS_Ver["Versi OS / Setelan<br/>(Kunci Layar, Biometrik)"]

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

        %% Layer 3: Client Software
        subgraph Client_Layer ["Lapisan 3: Perangkat Lunak Klien"]
            Browser["Browser: Chrome, Safari, Edge<br/>+ Versi"]
            App["Aplikasi Native / WebView<br/>+ Versi Aplikasi"]

            OS_Ver --> Browser
            OS_Ver --> App
        end

        %% Layer 4: WebAuthn Operation
        subgraph Op_Layer ["Lapisan 4: Operasi WebAuthn"]
            OpType{"Jenis Operasi"}

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

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

        %% Layer 5: Sub-types & Complexity
        subgraph Modality ["Lapisan 5: Modalitas & Kompleksitas"]
            Sub_CUI["CUI / UI Bersyarat"]
            Sub_Auto["Operasi Otomatis"]
            Sub_CDA["CDA / Autentikasi Lintas Perangkat"]

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

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

        %% Classification
        Classification{"Klasifikasi"}

        Exp["Kesalahan yang Diharapkan<br/>(Pengguna Membatalkan Upacara)"]:::expected
        Unexp["Kesalahan Tak Terduga<br/>(Sistem/Crash/Tidak Diketahui)"]:::unexpected

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

        Classification --> Exp
        Classification --> Unexp

        %% Detection Logic
        subgraph Detection ["Tujuan Deteksi"]
            P1["P1: Masalah Login"]
            P2["P2: Masalah Pembuatan"]
            Baseline["Deteksi Penyimpangan Baseline<br/>(Peningkatan yang Diharapkan)"]
            NewErr["Deteksi Anomali Baru<br/>(Peningkatan Tak Terduga)"]
        end

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

        %% Actionable Outcomes
        subgraph Action ["Tindakan Mitigasi"]
            Fix["Terapkan Perbaikan Darurat / Versi Baru"]:::action
            Fallback["Aktifkan Fallback Otomatis<br/>(Nonaktifkan Passkey)"]:::action
        end

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

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

Wawasan utamanya: nama `error.name` mentah hanya masuk akal jika Anda mengetahui di lapisan Lingkungan mana kesalahan itu diproduksi, Operasi mana yang sedang berjalan, dan apakah kesalahan tersebut Diharapkan atau Tidak Terduga. Bagian di bawah ini membahas apa yang harus dicatat dan bagaimana menindaklanjutinya.

## 11. Apa yang harus dicatat agar Kesalahan dapat di-debug

Sebagian besar klasifikasi kesalahan dalam artikel ini dapat dilakukan dengan sinyal sisi klien saja. SDK observabilitas sisi klien menangkap cukup konteks untuk mengklasifikasikan sebagian besar kesalahan WebAuthn. Ini juga cara arsitektur SDK observabilitas Corbado: lapisan sisi klien menangani atribusi kesalahan, waktu, konteks operasi, dan deteksi platform. Pencatatan sisi server menambahkan lapisan kedua untuk kegagalan yang hanya dapat dilihat oleh backend.

Persyaratan utamanya: setiap upaya harus dapat digabungkan ujung-ke-ujung (end-to-end). ID korelasi bersama (mis., `auth_flow_id`) menghubungkan konteks sisi klien dengan hasil verifikasi server.

### 11.1 Sinyal Sisi Klien (SDK Frontend)

| **Sinyal**                                 | **Mengapa itu penting**                                                                                                                   |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `error.name` + kelompok alasan dinormalisasi | Kesalahan browser mentah + klasifikasi Anda                                                                                              |
| Jenis operasi                             | UI Bersyarat, login modal, buat manual, buat bersyarat, tambah-otomatis. **CDA (Autentikasi Lintas Perangkat)** adalah kompleksitas tersendiri.   |
| Konteks Lingkungan Penuh                   | OS + Versi, Browser + Versi, **Merek/Model Perangkat Keras**, **Pengaturan Autentikator** (mis., GPM diaktifkan?)                           |
| Autentikator / konteks pengelola kredensial | Ekstensi dan kerusakan penyedia                                                                                                      |
| Waktu menuju kesalahan dari mulai operasi   | Penolakan segera (`<1 dtk`) vs pembatalan pengguna (1-15 dtk) vs waktu habis (30 dtk+)                                                                 |
| Status Jaringan / Konektivitas              | Kesalahan jaringan seringkali bermanifestasi sebagai kesalahan klien. Lacak jika pengguna sedang offline dan **antrekan log** untuk dikirim ketika konektivitas pulih. |
| Apakah UI QR/hybrid muncul                  | Lokal vs kegagalan lintas-perangkat                                                                                                        |
| Id korelasi (`auth_flow_id`)               | Gabungkan dengan log server                                                                                                                |

### 11.2 Sinyal Sisi Server (Verifikasi Backend)

Kegagalan verifikasi server terjadi setelah browser mengembalikan kredensial dan tantangan yang ditandatangani. Ini harus berupa kesalahan terstruktur dengan kode eksplisit, jangan dicampur ke dalam keranjang yang sama dengan nama `DOMException` sisi klien. Lihat:
Implementasi server WebAuthn.

| **Sinyal**                               | **Mengapa ini penting**                                                                                                                                                                             |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Tantangan tidak cocok / tantangan kedaluwarsa   | Masalah waktu sesi atau putar ulang                                                                                                                                                                |
| Asal / RP ID tidak cocok                  | Kesalahan konfigurasi multi-domain                                                                                                                                                                |
| Tanda tangan tidak valid / kredensial tidak ditemukan | Kredensial dihapus atau rusak. Kasus umum: login UI bersyarat dengan kunci sandi yang sudah dihapus pengguna di sisi server. Gunakan Signal API untuk menjaga sinkronisasi daftar kredensial klien dan server. |
| User handle mismatch                     | Masalah pemetaan akun                                                                                                                                                                         |
| Correlation id (`auth_flow_id`)          | Gabungkan dengan konteks sisi klien                                                                                                                                                                  |

Jika Anda menginginkan model alur penuh (penurunan pada setiap langkah dan konversi antar langkah), lihat:
telemetri passkey untuk memahami penurunan.

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

Dengan adanya data ini, kesimpulannya menjadi sederhana: sebagian besar "kesalahan" menjadi perbaikan UX, perbaikan cakupan, atau perbaikan konfigurasi. Namun, membangun dan memelihara klasifikasi ini sendiri merupakan pekerjaan berkelanjutan yang signifikan.

## 12. Melampaui Nama Kesalahan: bagaimana Corbado mengubah Kesalahan mentah menjadi Sinyal yang dapat ditindaklanjuti

Daftar periksa log di atas menangkap sinyal mentah. Di produksi pada skala besar, `error.name`
saja tidak cukup. Membangun klasifikasi ini sendiri adalah pekerjaan berkelanjutan yang signifikan:
pesan kesalahan berubah seiring dengan rilis browser dan OS baru,
penyedia pengelola kata sandi mengirimkan pembaruan yang mengubah
perilaku upacara dan ciri kesalahan baru muncul dengan peluncuran fitur baru.

### 12.1 Mengapa `error.name` saja tidak cukup

`NotAllowedError` yang sama dapat berarti enam hal yang berbeda bergantung pada tiga dimensi
yang tidak dipisahkan oleh browser untuk Anda:

| **Dimensi**                | **Apa yang diberikan browser** | **Apa yang sebenarnya Anda butuhkan**                                                             | **Contoh**                                                                                                 |
| ---------------------------- | -------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| **Konteks operasi**        | `NotAllowedError`          | Apakah itu UI bersyarat, login modal, pembuatan manual, pembuatan bersyarat, atau lampiran otomatis? | Android mengembalikan "unknown error" yang sama untuk pembatalan masuk (diharapkan) dan kegagalan pembuatan (tidak diharapkan) |
| **Pengaturan waktu**                   | Tidak ada data durasi           | Penolakan instan (`<1 dtk`) vs pembatalan pengguna (1-15 dtk) vs batas waktu (30 dtk+)                             | 200 md = penolakan lingkungan; 5 dtk = pengguna melihat dialog dan membatalkannya; 35 dtk = batas waktu                            |
| **Platform + autentikator** | `error.name` generik       | OS, browser, versi, pengelola kredensial untuk setiap kesalahan                               | "pengguna menutup dialog" di Chrome dan "isi otomatis tidak tersedia" di Safari keduanya muncul sebagai `NotAllowedError`    |

### 12.2 Apa yang ditangkap SDK pengamatan Corbado

Ini adalah masalah yang dibangun untuk diselesaikan oleh [SDK observabilitas Corbado](https://www.corbado.com/pricing). Ini adalah integrasi antarmuka ringan yang terletak di atas implementasi kunci sandi Anda yang sudah ada, bekerja dengan server WebAuthn mana pun dan IDP apa pun, dan secara otomatis mengklasifikasikan setiap kesalahan WebAuthn ke dalam ketiga dimensi tersebut:

| **Kemampuan**                       | **Apa yang dilakukannya**                                                                                                                                                                                                                                                        |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Atribusi kesalahan**                | Menangkap OS, versi OS, browser, versi browser dan autentikator pada setiap upaya upacara                                                                                                                                                                         |
| **Mode operasi**                   | Menghubungkan setiap kesalahan dengan operasi spesifik (UI bersyarat, login modal, pembuatan manual, pembuatan bersyarat, penambahan otomatis) sehingga `NotAllowedError` yang sama mengarah ke akar penyebab yang berbeda                                                                             |
| **Waktu dari awal tindakan**         | Merekam durasi dari permulaan upacara untuk membedakan penolakan segera, pembatalan pengguna dan waktu habis tanpa menerka-nerka                                                                                                                                               |
| **Klasifikasi kesalahan cerdas** | Mencocokkan dengan seluruh konteks kesalahan (bukan hanya nama), melakukan normalisasi atas ragam **Lingkungan** (OS, Hardware, Pengaturan). Memprioritaskan grup kesalahan berbeda seperti **CDA** vs. Lokal, dan membedakan kesalahan yang **Diharapkan (Pengguna Membatalkan)** dari **Tak Terduga (Sistem Gagal)**. |
| **Fragmentasi pengelola kata sandi**   | Mendeteksi saat perpanjangan dari pengelola kredensial (Bitwarden, 1Password, LastPass) mengintersep upacara lantas mereturn jawaban di luar standar, sambil menepis kerusakan akibat platform yang tersirat via ekstensi                                                                         |

Inilah tingkatan pemantauan (Observe): penampakan ke perkara-perkara internal yang berkisah soal pengamatannya, tanpa turut mengguncang maupun membuat rombakan struktur pada tatanan program buatanmu.

### 12.3 Dua Cara untuk men-debug: Top-Down dan Bottom-Up

Konsol manajemen Corbado mendukung dua jalur investigasi:

**Top-down (dasbor ke akar penyebab):**

1. **Pantau untuk dua jenis anomali berbeda:**
    - **Peningkatan Kesalahan yang Diharapkan (Penyimpangan Baseline):** Apakah lingkungan tertentu (mis.,
      iOS 18.2 di iPhone 15) mengalami
      peningkatan bertahap dalam "pembatalan pengguna"? Ini sering menunjukkan gesekan UX yang diperkenalkan oleh
      pembaruan OS.
    - **Peningkatan Kesalahan Tak Terduga (Lonjakan):** Kesalahan yang sama sekali baru atau lompatan tiba-tiba
      kegagalan. Ini biasanya menunjukkan perubahan yang merusak (pembaruan tumpukan IDP internal) atau
      regresi dalam versi browser baru.
2. **Prioritaskan menurut dampak:**
    - **P1: Masalah Login.** Jika tingkat keberhasilan login menurun, segera waspada.
    - **P2: Masalah Pembuatan.** Pantau tren, tetapi hindari membangunkan teknisi untuk lonjakan "pembatalan
      pengguna" dalam alur pembuatan.
3. **Selidiki Lingkungan:** Gunakan dimensi yang lebih rinci (Hardware, Auth Settings)
   untuk mengisolasi apakah masalah tersebut bersifat global atau spesifik untuk "perangkat Samsung
   dengan Android 14".
4. **Mitigasi:** Jika lonjakan kritis terdeteksi, siapkan **Kill Switch**.
   Secara otomatis atau manual nonaktifkan kunci sandi untuk lingkungan spesifik itu dan kembali
   ke OTP/Kata sandi untuk menjaga tingkat login saat Anda menyelidiki.

**Bottom-up (pola kesalahan ke dampak):**

1. Mulai dari tampilan klasifikasi kesalahan. Tinjau pola kesalahan yang diklasifikasikan dan volumenya.
2. Perbaiki pemetaan kesalahan saat pola baru muncul (mis. versi browser baru yang merilis
   pesan kesalahan yang berbeda).
3. Kesalahan berkorelasi silang dengan perubahan KPI dan dimunculkan sebagai anotasi di dasbor,
   sehingga lonjakan dalam pola kesalahan tertentu secara otomatis ditautkan ke metrik yang dipengaruhinya.

Kedua jalur menyatu: top-down memberi tahu Anda ada sesuatu yang salah, bottom-up memberi tahu Anda alasannya.
[Asisten Analitik AI](https://www.corbado.com/ai-analytics-assistant) menghubungkan keduanya dengan memungkinkan Anda mengajukan
pertanyaan dalam bahasa alami di seluruh data kesalahan dan metrik adopsi.

Tim yang ingin menindaklanjuti sinyal ini dapat beralih ke **Adopt**, yang menambahkan
[intelijen passkey](https://docs.corbado.com/corbado-connect/features/passkey-intelligence)
untuk secara otomatis membatasi upacara, mengoptimalkan prompt pendaftaran dan menyembuhkan status passkey yang rusak. Untuk lingkungan yang diatur atau penyebaran skala besar (hyperscale), **Enterprise** menambahkan
hosting penyewa tunggal, integrasi SIEM dan konfigurasi yang mematuhi
PSD2.

## 13. Kesimpulan

Nama kesalahan WebAuthn bukan sebuah vonis. Itu adalah petunjuk - dan itu hanya dapat ditindaklanjuti
saat Anda menghubungkannya ke jenis operasi, waktu, dan konteks platform.

- **Apa arti nama kesalahan WebAuthn yang paling umum di produksi?** Sebagian besar memetakan ke sekumpulan kecil lapisan: aliran kontrol pengguna (`NotAllowedError`), siklus hidup/konkurensi aplikasi
  (`AbortError`), konteks/konfigurasi keamanan (`SecurityError`), atau bug opsi/status
  (`InvalidStateError`, `ConstraintError`, `DataError`). Sebagian besar volume adalah
  `NotAllowedError`, dan sebagian besar dari itu adalah perilaku yang diharapkan (pengguna menutup prompt).
- **Bagaimana Anda membedakan `NotAllowedError`?** Gunakan waktu (penolakan instan vs pembatalan pengguna
  vs batas waktu), indikator QR/hibrida (ketidaksesuaian ketersediaan), konteks aktivasi pengguna
  (terutama di iOS/Safari) dan jenis operasi (UI bersyarat vs login modal
  vs pembuatan passkey vs pembuatan bersyarat). Jangan memperlakukan semua `NotAllowedError` sebagai satu
  mode kegagalan.
- **Mengapa jenis operasi penting?** `error.name` yang sama selama
  login UI bersyarat adalah sinyal yang sama sekali berbeda dari
  pada saat pembuatan bersyarat atau pembuatan passkey manual (pengguna menutup dialog).
  Mencatat jenis operasi beserta kesalahannya adalah hal yang mengubah `NotAllowedError` umum
  menjadi kelompok yang dapat ditindaklanjuti.
- **Konteks minimum apa yang membuat kesalahan dapat di-debug?** Tangkap `error.name`, jenis operasi,
  waktu terjadinya kesalahan dari awal operasi, tipe alur, apakah UI QR/hibrida ditampilkan,
  OS/browser/perangkat (termasuk versi), id korelasi (`auth_flow_id`) dan penolakan verifikasi
  server sebagai kode eksplisit.

Dua aturan praktis yang berlaku untuk semua jenis kesalahan: jangan pernah menunjukkan kesalahan peramban mentah kepada
pengguna - selalu berikan alur alternatif yang jelas - dan pisahkan percobaan lokal dari percobaan QR/hibrida
lintas perangkat, karena mereka gagal karena alasan yang berbeda dan memerlukan perbaikan yang berbeda.
Pada skala besar, memelihara klasifikasi kesalahan di seluruh peramban, versi OS, dan pengelola
kredensial adalah pekerjaan yang berkelanjutan. Pertimbangkan untuk menggunakan SDK observabilitas dengan pustaka pola yang dipelihara
daripada membangunnya dari awal.

## Pertanyaan yang Sering Diajukan

### Bagaimana cara membedakan antara pengguna yang membatalkan permintaan kunci sandi dan perangkat yang tidak memiliki kunci sandi?

Di web, peramban menyatukan kedua kasus tersebut menjadi `NotAllowedError` demi alasan privasi, jadi
Anda tidak dapat membedakannya secara langsung. Gunakan waktu sebagai proksi: kesalahan di bawah 1 detik biasanya
berarti penolakan lingkungan atau hilangnya kemampuan, sedangkan 1-15 detik menunjukkan bahwa pengguna
melihat dan mengabaikan dialog. Di aplikasi asli iOS dan Android, pengaturan
`preferImmediatelyAvailableCredentials` sebelum permintaan memberi Anda sinyal "tidak ada
kredensial" yang jelas (iOS kode 1005, Android `GetCredentialRequest`) sebelum UI apa pun ditampilkan.

### Mengapa tingkat kesalahan WebAuthn saya sangat tinggi meskipun kunci sandi tampaknya berfungsi bagi sebagian besar pengguna?

Dalam pengerahan kunci sandi skala besar yang dioptimalkan, lebih dari 95% kesalahan WebAuthn yang tercatat adalah
pembatalan pengguna yang wajar, bukan kegagalan sistem. Melacak jumlah `error.name` mentah tanpa
memisahkan "pengguna menutup prompt" dari kegagalan sungguhan akan melambungkan metrik kesalahan dan menutupi
kemunduran sesungguhnya yang tersembunyi di dalam banyaknya `NotAllowedError`. Pisahkan perhitungan Anda berdasarkan
jenis operasi dan perlakukan keranjang yang dibatalkan oleh pengguna terpisah dari kesalahan yang tak terduga seperti
`SecurityError`, `ConstraintError` serta `DataError`.

### Apa maksud dari kode ASAuthorizationError 1005 di iOS dan bagaimana sebaiknya saya menggunakannya?

Kode iOS 1005 (`NotInteractive`) berarti tidak ada kunci sandi yang tersedia pada perangkat saat
`preferImmediatelyAvailableCredentials` diatur pada `ASAuthorizationController`, dan tak satu pun UI
ditampilkan kepada pengguna. Ini merupakan tanda bersih bahwa "kunci sandi tak terdeteksi keberadaannya di perangkat ini", sesuatu yang
browser web gagal berikan karena hambatan privasi. Biasakan mengklasifikasikannya berdasarkan kode 
numerik, bukan pada `localizedDescription`, sebab seluruh rangkaian pesan dari Apple diterjemahkan ke tak kurang dari 30
bahasa dan tak jarang mengalami perombakan antar rilis OS.

### Bagaimana sebaiknya saya menangani NotAllowedError selama pembuatan bersyarat atau alur tambah passkey yang dipicu otomatis?

Selama pembuatan bersyarat, `NotAllowedError`, `AbortError` dan `InvalidStateError` merupakan
hasil yang diharapkan dan harus diabaikan tanpa menimbulkan gangguan, alih-alih diperlihatkan sebagai ralat.
`NotAllowedError` menandakan bahwa fitur isi otomatis (autofill) tak tersedia atau tab halaman telah ditinggalkan, sementara
`InvalidStateError` memberitahukan bahwasanya kunci sandi telah tersedia di penyedia. Sebelum memanggil fungsi
tersebut, pakailah `getClientCapabilities()` dalam memastikan kompatibilitas `conditionalCreate` dan pantau 
visibilitas dokumen di halaman demi mencegah penggelembungan hitungan galat (error) Anda.

### Konteks apa yang harus saya sertakan bersamaan dengan error.name supaya kegagalan WebAuthn bisa benar-benar di-debug?

Catat jenis operasional (UI bersyarat, log masuk berbasis modal, pembuatan cara usang, atau penciptaan 
bersyarat beserta perlekatan otomatisnya), waktu sejak mulai terpicu sampai ralat mengemuka, tipe OS, rupa sistem perambah (browser), varian
perangkat (mesinnya), keterlihatan bentuk UI-nya, berikut rujukan keterkaitan (correlation ID) penyambung 
notifikasi ralat dari pangkalan datanya.
Penolakan dari pihak belakang penyaji (seperti selisih angka kode dan tak samanya rujukan nama log, plus
ketiadaan kata-kuncinya di brankas) wajib tertuang melalui susunan struktur dengan baik, tanpa dicampur dengan kumpulan galat 
yang datangnya dari pihak gawai `DOMException`. Elemen-elemen itu jika dihimpun mampu mengarahkan hampir
semua tipe kepalsuan hingga tertampung rapi dalam ember-ember solusinya, bukan cuma diterka-terka acak.
