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
- Include the form with id `${providerID}-form` (e.g. id="passkey-form") in the page markup
- Verify the provider id in the client setup matches the id used in the DOM element
- Load the script with defer or run it on DOMContentLoaded so the form exists when queried
- 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
- Render the required form markup before the WebAuthn client script runs (use defer/DOMContentLoaded)
- Keep the element id exactly `${providerID}-form` in sync with provider config
- When using custom pages, verify all WebAuthn markup is present in your template
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
- Authenticator not found.
- Authenticator not found.
- Authenticator not found.
- Authenticator not created
- Verification Token not found
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/78fcc95ad116481c.
Report an issue: GitHub.