dotnet/aspnetcore · warning · Error
Please enter a username.
Error message
Please enter a username.
What it means
Thrown by fetchNewCredential() in the PasskeyUI sample when the username form field is empty before initiating WebAuthn attestation (registration). It is a client-side guard that prevents sending an empty username to the /attestation/options endpoint. Registration requires a username so the server can associate the new credential with an account.
Solutions
- Add required attribute to the username input in the Razor/HTML template so the browser blocks empty submission.
- Trim and validate the username client-side before calling fetchNewCredential, showing a user-friendly message.
- Ensure the form actually contains an input named 'username' matching FormData expectation.
Example fix
// before
async function fetchNewCredential(username) {
if (!username) {
throw new Error('Please enter a username.');
}
// ...
}
// after (validate at call site, keep guard)
const username = (new FormData(form).get('username') || '').trim();
if (!username) {
statusMessage.textContent = 'Please enter a username.';
return;
}
credential = await fetchNewCredential(username); Defensive patterns
Strategy: validation
Validate before calling
function readUsername(form) {
const v = new FormData(form).get('username');
return (v == null ? '' : String(v)).trim();
}
const username = readUsername(form);
if (!username) {
statusMessage.textContent = 'Please enter a username.';
return; // do not call fetchNewCredential
} Try / catch
try { await fetchNewCredential(username); } catch (e) { if (e.message === 'Please enter a username.') { statusMessage.textContent = e.message; return; } throw e; } Prevention
- Add the HTML required attribute to the username input for native browser validation.
- Trim the username before the WebAuthn flow and short-circuit with a UI message.
- Keep the form's input name attribute exactly 'username' so FormData.get returns the field.
When it happens
Trigger: User clicks the 'register' submit button on the auth form (name='action', value='register') with the username input empty or whitespace-only. FormData(form).get('username') returns null or empty string, which is falsy, so fetchNewCredential throws immediately before any fetch.
Common situations: First-time passkey enrollment where the user skipped the username field; form rendered without a username input (template change); HTML5 required attribute missing so the browser doesn't block submission; programmatic form.submit() bypassing the UI.
Related errors
- Unknown action
- Some passkey features are missing. Please update your…
- Unknown passkey operation
- A valid url is required.
- assembly must be defined when using a descriptor.
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/14fa7f30f187937e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Identity/samples/IdentitySample.PasskeyUI/wwwroot/app.js:32
function enableRouteScripts() {
Blazor.addEventListener('enhancednavigationend', executeScript);
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', executeScript);
} else {
executeScript();
}
}
// Define home page JS functionality.
addRouteScript('/', async () => {
let abortController;
const form = document.getElementById('auth-form');
const statusMessage = document.getElementById('status-message');
async function fetchNewCredential(username) {
if (!username) {
throw new Error('Please enter a username.');
}
const optionsResponse = await fetch('/attestation/options', {
method: 'POST',
body: JSON.stringify({
username,
}),
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
});
const optionsJson = await optionsResponse.json();
const options = PublicKeyCredential.parseCreationOptionsFromJSON(optionsJson);
abortController?.abort();
abortController = new AbortController();
return await navigator.credentials.create({
publicKey: options,View on GitHub (pinned to 3600ca084e)