QuantumNous/new-api · error · Error

Unable to build Passkey assertion

Error message

Unable to build Passkey assertion

What it means

Thrown in verifyPasskey() when buildAssertionResult(credential) returns a falsy value after a successful navigator.credentials.get(). The helper converts the PublicKeyCredential into the JSON-serializable assertion the finish endpoint expects; null means the credential's response was missing required fields (clientDataJSON, authenticatorData, signature) or had an unexpected shape.

Solutions

  1. Log the credential object (id, type, response keys) to see which field is absent.
  2. If using a mock in tests, make it include response.clientDataJSON, authenticatorData, signature (and userHandle when present), base64url-encoded.
  3. Try a different authenticator/device to rule out the specific security key.
  4. Harden buildAssertionResult to report which field was missing instead of returning null.
Defensive patterns

Strategy: type-guard

Type guard

const isUsableAssertion = (a: unknown): boolean =>
  typeof a === 'object' && a !== null &&
  typeof (a as { id?: unknown }).id === 'string' &&
  typeof (a as { response?: { signature?: unknown } }).response?.signature === 'string'

Try / catch

try {
  await verify('passkey', scope)
} catch (e) {
  if (/assertion/i.test(getErrorMessage(e))) {
    promptUserToRetryWithDifferentAuthenticator()
  }
  throw e
}

Prevention

When it happens

Trigger: The authenticator returns a credential whose response lacks signature or authenticatorData; the browser hands back a credential object whose response is an unexpected subtype; a polyfill or testing library returning a minimal fake credential.

Common situations: Testing with mocked navigator.credentials that omits response fields; exotic authenticators or security keys with non-standard attestation responses; browser extension interfering with the credentials API.

Related errors


AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15). Data as JSON: /api/errors/c8dc8bb994ebd710. Report an issue: GitHub.

Appendix: source

Thrown at web/src/features/auth/secure-verification/api.ts:162

    const publicKey = prepareCredentialRequestOptions(
      beginResponse.data?.options ?? beginResponse.data
    )
    const flowToken = beginResponse.data?.flow_token
    if (!flowToken) {
      throw new Error(i18next.t('Verification flow expired'))
    }

    const credential = (await navigator.credentials.get({
      publicKey,
    })) as PublicKeyCredential | null

    if (!credential) {
      throw new Error(i18next.t('Passkey verification was cancelled'))
    }

    const assertion = buildAssertionResult(credential)
    if (!assertion) {
      throw new Error(i18next.t('Unable to build Passkey assertion'))
    }

    const finishResponse = await finishPasskeyVerification(flowToken, assertion)
    if (!finishResponse.success) {
      throw new Error(
        finishResponse.message || i18next.t('Passkey verification failed')
      )
    }

    if (!finishResponse.data?.proof_token) {
      throw new Error(i18next.t('Verification proof was not returned'))
    }
    return finishResponse.data
  } catch (error: unknown) {
    if (error instanceof DOMException && error.name === 'NotAllowedError') {
      throw new Error(
        i18next.t('Passkey verification was cancelled or timed out'),
        { cause: error }

View on GitHub (pinned to e2c7aa7b10)