nextauthjs/next-auth · error · Error

Form '${formID}' not found

Error message

Form '${formID}' not found

What it means

The WebAuthn client injects per-provider forms into the page and getForm() queries the DOM for #<providerID>-form; if the form element is missing it throws. The client script cannot find the markup it needs to submit the WebAuthn flow.

Source

Thrown at packages/core/src/lib/utils/webauthn-client.js:66

    if (!res.ok) {
      console.error("Failed to fetch options", res)

      return
    }

    return res.json()
  }

  /**
   * Get the webauthn form from the page
   *
   * @returns {HTMLFormElement}
   */
  function getForm() {
    const formID = `#${providerID}-form`
    /** @type {HTMLFormElement | null} */
    const form = document.querySelector(formID)
    if (!form) throw new Error(`Form '${formID}' not found`)

    return form
  }

  /**
   * Get formFields from the form
   *
   * @returns {HTMLInputElement[]}
   */
  function getFormFields() {
    const form = getForm()
    /** @type {HTMLInputElement[]} */
    const formFields = Array.from(
      form.querySelectorAll("input[data-form-field]")
    )

    return formFields
  }

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Include the form with id `${providerID}-form` (e.g. id="passkey-form") in the page markup
  2. Verify the provider id in the client setup matches the id used in the DOM element
  3. Load the script with defer or run it on DOMContentLoaded so the form exists when queried
  4. If using a custom page, copy the required WebAuthn form markup from the default page

Example fix

// before
<div id="passkey-widget"></div> <!-- no form -->
// after
<form id="passkey-form"><input type="hidden" name="username" /></form>
Defensive patterns

Strategy: type-guard

Validate before calling

const form = document.querySelector(`#${providerID}-form`);
if (!(form instanceof HTMLFormElement)) throw new Error(`WebAuthn form missing for provider "${providerID}"`);

Type guard

function getWebAuthnForm(providerID: string): HTMLFormElement | null { const el = document.querySelector(`#${providerID}-form`); return el instanceof HTMLFormElement ? el : null; }

Try / catch

try { const form = getForm(); await webAuthnFlow(form) } catch (e) { if (String(e.message).includes("not found")) { console.error(`Add <form id="${providerID}-form"> to the page`); return; } throw e; }

Prevention

When it happens

Trigger: Rendering the WebAuthn page without the required form element with id '<providerID>-form', a mismatched provider id between markup and configuration, or the script running before the DOM is rendered.

Common situations: Custom sign-in pages that omit the WebAuthn form markup; typos/different casing in the provider id used in the element id; script loaded in <head> without defer so the form does not exist yet.

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/78fcc95ad116481c. Report an issue: GitHub.