---
title: "Why is my registration form not showing password errors? · Proxy Mail QA"
description: "A password that breaks the rules gets no error, or the form moves on anyway. The eight usual causes, and one test that tells you where to look."
url: https://proxymail.qa/solve/why-is-my-registration-form-not-showing-password-errors
---

1. [Home](https://proxymail.qa/)
2. [What we solve](https://proxymail.qa/solve)

# Why is my registration form not showing an error for passwords that don't meet the criteria?

Someone types a password that's too short, presses \*\*Create account\*\*, and nothing happens. Or the page moves on as if all was well. The cause is almost always one of eight things, and one test tells you which group to look in.

Updated 5 November 2026

> **Our recommendation, up front.** We make Proxy Mail QA, so we’re not neutral, but this problem is in your code and the fix is too: no product fixes it for you. We recommend Proxy Mail QA for two parts of the job: test passwords that break your rules on purpose, made for your field’s limits, and finding out what really happened behind a silent form, because if a verification email arrives, your server made the account. It doesn’t find the bug in your code; your browser’s DevTools, or your AI agent reading the code, do that.

## First, find out which of three things is happening

Open your browser’s DevTools on the **Network** tab, then submit a password that breaks your rules, such as one character under the minimum. To get one made for your field, use the **Edge-case password** list (“Should be rejected”) on the card that [Proxy Mail QA for Chrome](https://proxymail.qa/chrome-extension)’s key button opens in the password field, or `get_password_variants` with your rules. Use a new test address, so you can see whether an email comes.

| What you see                                               | What it means                                                                    | Look at        |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------- |
| No request is sent                                         | The browser or your code stopped the form, but showed nothing                    | Causes 1 to 4  |
| A request is sent and the server refuses it (a 400 or 422) | The server did its job; the page didn’t show the answer                          | Causes 5 and 6 |
| A request is sent and the server accepts it                | The server allows the password. A verification email arrives at the test address | Cause 7        |

The third is the one people miss. A form “with no error” may simply have nothing to report, because the server’s rule is looser than the one on the page. In the [app](https://app.proxymail.qa/?mode=signup), the verification email shows on the test address’s row. An agent or a test can use `expect_no_email`, which passes only if nothing arrives.

## The usual causes

### The form never sent anything

1. **`novalidate` with nothing in its place.** The form, or a form library, turns off the browser’s own messages (`novalidate`, or `noValidate` in React), and your own validation never renders an error.
2. **The rules aren’t on the input.** Without `minlength`, `maxlength` or `required`, the browser has nothing to check. And `validity.tooShort` is set only after the person types, so a value set by a script can slip past it.
3. **The error exists but is hidden.** CSS hides it, it’s rendered under the wrong name (`errors.password` when the field is `newPassword`), or it only shows once the field is “touched” and submitting doesn’t mark it touched.
4. **A custom component wraps the input.** The form library is connected to the wrapper, not the real `<input>`, so it checks an empty value, or the component never passes the error message down.

### The server refused it, and the page didn’t say

1. **The error is swallowed.** The code shows “Check your email” whatever the response, uses `catch {}` with nothing in it, or only handles `res.ok`. Some auth clients don’t throw: Supabase’s `signUp` returns `{ data, error }`, so a `try`/`catch` never sees a refused password.
2. **The error comes back in a shape the page doesn’t read.** The server says `{ "message": "..." }` and the page looks for `errors.password`. Map each service’s error to the field it’s about.

### The server accepted it

1. **The page’s rule is stricter than the server’s.** The page says 15 characters; the auth service’s setting allows 6\. Set the minimum in the service’s settings, or in your own server code, and keep it equal to what the page says.

### There is an error, but not everyone can tell

1. **It isn’t announced.** It’s shown only in red, far from the field, or off-screen on a phone, and isn’t linked to the field. Screen reader users hear nothing. Link it with `aria-describedby`, set `aria-invalid="true"`, and move focus to the field.

## A pattern that shows errors reliably

Framework-free, so the idea carries over to React, Vue or anything else:

HTML

```html
<form id="signup" novalidate>
  <label for="password">Password</label>
  <p id="password-rules">At least 15 characters. Any letters, numbers, symbols or spaces.</p>
  <input
    id="password"
    name="password"
    type="password"
    autocomplete="new-password"
    minlength="15"
    maxlength="128"
    required
    aria-describedby="password-rules password-error"
  />
  <p id="password-error" class="error" hidden></p>
  <button>Create account</button>
</form>

<script>
  const form = document.getElementById('signup');
  const password = form.elements.password;
  const error = document.getElementById('password-error');

  // Count characters, not UTF-16 units, and don't rely on validity.tooShort.
  function rule(input) {
    const length = [...input.value].length;
    if (length === 0) return 'Enter a password.';
    if (length < input.minLength) return `Use at least ${input.minLength} characters.`;
    if (length > input.maxLength) return `Use at most ${input.maxLength} characters.`;
    return '';
  }

  function show(message) {
    error.textContent = message;
    error.hidden = !message;
    password.setAttribute('aria-invalid', message ? 'true' : 'false');
  }

  password.addEventListener('input', () => {
    if (!error.hidden) show(rule(password));
  });

  form.addEventListener('submit', async (event) => {
    event.preventDefault();
    const message = rule(password);
    if (message) {
      show(message);
      password.focus();
      return;
    }
    const res = await fetch('/api/signup', { method: 'POST', body: new FormData(form) });
    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      show(body.errors?.password ?? body.message ?? 'Something went wrong. Please try again.');
      password.focus();
      return;
    }
    location.assign('/check-your-email');
  });
</script>

```

The server checks the same rules and answers a refused password with a 422 and `{ "errors": { "password": "Use at least 15 characters." } }`, which the page shows at the field.

A note on `maxlength`: the browser stops typing at the limit and cuts pasted text short without saying so. Set it well above what a password manager makes, or someone saves a password that’s longer than the one your app received.

## Ask your agent to find it

With Proxy Mail QA connected in Qoder ([Marketplace](https://qoder.com/en/marketplace/connector?id=proxymail-qa)):

Prompt

```text
My sign-up form at https://staging.acme.dev/signup shows no error when the password
breaks the rules (15 to 128 characters). Using Proxy Mail QA, get_password_variants
with min_length 15 and max_length 128, and submit each reject value with a new test
address (a plus tag on one address for each). For each, tell me whether a request was
sent, what the server answered, what the page showed, and whether a verification email
arrived (expect_no_email).
Then find the cause in the code and fix it, so the error shows at the field, is
announced to screen readers, and the server enforces the same rule as the page.

```

## Prove it’s fixed

A Playwright test with the [proxymail-qa](https://proxymail.qa/docs/node) npm package, so it stays fixed:

TypeScript

```ts
import { expect, test } from '@playwright/test';
import { ProxyMailQA } from 'proxymail-qa';

const qa = new ProxyMailQA(); // reads PROXYMAIL_QA_API_KEY

test('a too-short password shows an error and makes no account', async ({ page }) => {
  const { reject } = await qa.passwordVariants({ minLength: 15, maxLength: 128 });
  const tooShort = reject.filter(({ value }) => [...value].length < 15);
  const { address } = await qa.createAddress();

  for (const [i, { tests, value }] of tooShort.entries()) {
    const tagged = address.replace('@', `+short${i}@`);
    const submitted = new Date();
    await page.goto('/signup');
    await page.getByLabel('Email').fill(tagged);
    await page.getByLabel('Password').fill(value);
    await page.getByRole('button', { name: 'Create account' }).click();

    await expect(page.locator('#password-error'), tests).toBeVisible();
    await qa.expectNoEmail(tagged, { since: submitted, timeout: 10 });
  }

  await qa.deleteAddress(address);
});

```

`expectNoEmail` throws as soon as a verification email arrives, which would mean the server made the account. A plus tag gives each try its own account in your app, and waiting on the tagged address only sees mail sent to it.

## What Proxy Mail QA doesn’t do here

- Find or fix the bug. It shows you what happened; the fix is in your form and your server.
- Check accessibility beyond this one error. Run axe DevTools, and try the form with a screen reader.
- Choose your rules. For that, see [How long should my registration form password be?](https://proxymail.qa/solve/how-long-should-my-registration-form-password-be)

## Try it on your next sign-up test

Free plan, no credit card. Create an address and watch the code or link arrive.

[Create a free account](https://app.proxymail.qa/?mode=signup&from=site-solve-why-is-my-registration-form-n)

## Related guides

- [Test sign-up and email verificationA fresh, private address for every sign-up test, with the verification link or code ready the moment it lands.](https://proxymail.qa/solve/email-verification-testing)
- [Test OTP and one-time login codesCodes pulled out of the email with a Copy button and a countdown when the email says how long they last.](https://proxymail.qa/solve/otp-code-testing)
- [Test magic links and passwordless sign-inSingle-use links that are never opened or prefetched on our side, so they still work when you click them.](https://proxymail.qa/solve/magic-link-testing)
- [Test password reset emailsRequest, receive and use reset links, and keep the new password saved next to the test account.](https://proxymail.qa/solve/password-reset-testing)
- [Stop sharing one Gmail inbox for QAPrivate, disposable addresses for every tester instead of one shared mailbox and a pile of plus-addresses.](https://proxymail.qa/solve/shared-test-inbox)
- [Take QA notes by voice with Wispr FlowDictate what each test account is for, its state and what you found, straight into its notes, in seconds.](https://proxymail.qa/solve/voice-notes-wispr-flow)
- [Verification link points to localhost:3000Why emails from staging link to localhost, how to fix it in Supabase, Firebase and other stacks, and how we flag it.](https://proxymail.qa/solve/localhost-links)
- [Common Supabase sign-up and login problemsEmails that never arrive, links that expire or sign nobody in, and sign-ups that fail, with the fix for each.](https://proxymail.qa/solve/supabase-auth-problems)
- [Common Firebase sign-up and login problemsMissing verification and reset emails, verified users who still look unverified, failing links and sign-up limits, with the fix for each.](https://proxymail.qa/solve/firebase-auth-problems)
- [Sign-up and login problems in vibe-coded appsThe login bugs AI-built apps usually ship with: emails only you receive, links to the preview, missing pages, and what to ask the builder.](https://proxymail.qa/solve/vibe-coded-login-problems)
- [Test sign-up emails in PlaywrightA complete Playwright test for sign-up codes and links, from a fresh inbox to the report on the pull request.](https://proxymail.qa/solve/playwright-email-tests)
- [Test sign-up emails in CypressA complete Cypress test for sign-up links and codes, with the email waits running as Cypress tasks.](https://proxymail.qa/solve/cypress-email-tests)
- [Test sign-up emails with pytestA complete pytest test for sign-up codes and links, with Playwright for Python or Selenium and a one-file helper.](https://proxymail.qa/solve/pytest-email-tests)
- [Test coupon codes and welcome offersThe coupon with its discount, end date and arrival time, what checkout did with it, and a failure when an expired or reused one is accepted.](https://proxymail.qa/solve/coupon-code-testing)
- [Test unsubscribe links and one-click unsubscribeThe unsubscribe headers and link checked on every marketing email, and a watch that flags any marketing after unsubscribing, with no time limit.](https://proxymail.qa/solve/unsubscribe-testing)
- [Test that a welcome offer can't be claimed twiceVersions of one address that reach the same inbox, and a check that fails when the same person got the offer more than once.](https://proxymail.qa/solve/welcome-offer-abuse)
- [AI sign-up page reviewLet an agent check the sign-up through to the email: delivery, the link, how it was sent, and that only one arrives.](https://proxymail.qa/solve/ai-sign-up-page-review)
- [AI registration page reviewAn agent tries every field with values made for it, then finishes the registration through the email.](https://proxymail.qa/solve/ai-registration-page-review)
- [Review a sign-up page by handA checklist for your browser and phone, in the order that finds the most problems.](https://proxymail.qa/solve/how-to-review-my-sign-up-page)
- [Review a simple sign-up form12 checks for a form with an email, a password and perhaps a name.](https://proxymail.qa/solve/review-a-simple-sign-up-form)
- [Review a multi-page sign-up formOne test account across every screen, and the verification email wherever it comes.](https://proxymail.qa/solve/review-a-multi-page-sign-up-form)
- [Review a financial sign-up formThe emails, age and country rules and awkward values in a financial sign-up, and what needs other tools.](https://proxymail.qa/solve/review-a-financial-website-sign-up-form)
- [An email address for testing registrationA new, real address for every registration try, with the code or link ready to use.](https://proxymail.qa/solve/email-for-checking-my-registration-form)
- [An email address for testing sign-inTest accounts with saved passwords and an inbox for codes, magic links and resets.](https://proxymail.qa/solve/email-for-checking-my-sign-in-form)
- [How long should a password be?NIST's numbers for password length and rules, and test passwords to check yours.](https://proxymail.qa/solve/how-long-should-my-registration-form-password-be)
- [Help me check my websiteA whole-site check in an afternoon, in the order that finds the costliest problems first.](https://proxymail.qa/solve/help-me-check-my-website)
- [Tools to build and check a websiteA toolkit by area, most of it free and none of it ours, except for account emails.](https://proxymail.qa/solve/tools-to-help-build-and-check-my-website)
- [What tools do I need for a website?The full list, then which parts a simple site can skip.](https://proxymail.qa/solve/what-tools-do-i-need-when-building-a-website)

[Built your app with an AI tool? Pick yours](https://proxymail.qa/built-with)
